home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / mpeg_stat-2.2 / video.c < prev    next >
C/C++ Source or Header  |  1995-05-10  |  100KB  |  3,574 lines

  1. /* MPEGSTAT - analyzing tool for MPEG-I video streams
  2.  * 
  3.  * Technical University of Berlin, Germany, Dept. of Computer Science
  4.  * Tom Pfeifer - Multimedia systems project - pfeifer@fokus.gmd.de
  5.  *
  6.  * Jens Brettin, Harald Masche, Alexander Schulze, Dirk Schubert
  7.  *
  8.  * This program uses parts of the source code of the Berkeley MPEG player
  9.  *
  10.  * ---------------------------
  11.  *
  12.  * Copyright (c) 1993 Technical University of Berlin, Germany
  13.  *
  14.  * for the parts of the Berkeley player used:
  15.  *
  16.  * Copyright (c) 1992 The Regents of the University of California.
  17.  * All rights reserved.
  18.  *
  19.  * ---------------------------
  20.  *
  21.  * Permission to use, copy, modify, and distribute this software and its
  22.  * documentation for any purpose, without fee, and without written agreement is
  23.  * hereby granted, provided that the above copyright notices and the following
  24.  * two paragraphs appear in all copies of this software.
  25.  * 
  26.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA 
  27.  * or the Technical University of Berlin BE LIABLE TO ANY PARTY FOR
  28.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  29.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  30.  * CALIFORNIA or the Technical University of Berlin HAS BEEN ADVISED OF THE 
  31.  * POSSIBILITY OF SUCH DAMAGE.
  32.  * 
  33.  * THE UNIVERSITY OF CALIFORNIA and the Technical University of Berlin 
  34.  * SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
  35.  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  36.  * PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE 
  37.  * UNIVERSITY OF CALIFORNIA and the Technical University of Berlin HAVE NO 
  38.  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, 
  39.  * OR MODIFICATIONS.
  40.  */
  41. /* 
  42.  * This file contains C code that implements
  43.  * the video decoder model.
  44.  */
  45.  
  46. #include <stdio.h>
  47. #include <stdlib.h>
  48. #include <assert.h>
  49.  
  50. #ifndef MIPS
  51. #include <sys/time.h>
  52. #else
  53. #include <sys/types.h>
  54. #include <sys/system.h>
  55. #endif
  56.  
  57. #include "decoders.h"
  58. #include "video.h"
  59. #include "util.h"
  60. #include "proto.h"
  61. #include "dither.h"
  62. #include "opts.h"
  63.  
  64. /* Declarations of functions. */
  65. static int ReconIMBlock();
  66. static void ReconPMBlock();
  67. static void ReconBMBlock();
  68. static void ReconBiMBlock();
  69. static void ReconSkippedBlock();
  70. static void DoPictureDisplay();
  71. static int ParseSeqHead();
  72. static int ParseGOP();
  73. static void PrintGOP();
  74. static int ParsePicture();
  75. static int ParseSlice();
  76. static int ParseMacroBlock();
  77. static void ProcessSkippedPFrameMBlocks();
  78. static void ProcessSkippedBFrameMBlocks();
  79.  
  80. /* Macro for returning 1 if num is positive, -1 if negative, 0 if 0. */
  81.  
  82. #define Sign(num) ((num > 0) ? 1 : ((num == 0) ? 0 : -1))
  83.  
  84.  
  85. /* CONSTANTS */
  86. /* Set up array for fast conversion from zig zag order to row/column
  87.    coordinates.
  88. */
  89.  
  90. const int zigzag[64][2] = {
  91.   0, 0, 1, 0, 0, 1, 0, 2, 1, 1, 2, 0, 3, 0, 2, 1, 1, 2, 0, 3, 0, 4, 1, 3,
  92.   2, 2, 3, 1, 4, 0, 5, 0, 4, 1, 3, 2, 2, 3, 1, 4, 0, 5, 0, 6, 1, 5, 2, 4,
  93.   3, 3, 4, 2, 5, 1, 6, 0, 7, 0, 6, 1, 5, 2, 4, 3, 3, 4, 2, 5, 1, 6, 0, 7,
  94.   1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6, 2, 7, 1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6,
  95.   2, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 5, 7, 6, 6,
  96.   7, 5, 7, 6, 6, 7, 7, 7};
  97. /* Array mapping zigzag to array pointer offset. */
  98.  
  99. const int zigzag_direct[64] = {
  100.   0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12,
  101.   19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35,
  102.   42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
  103.   58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63};
  104.  
  105. /* Set up array for fast conversion from row/column coordinates to
  106.    zig zag order.
  107. */
  108.  
  109. const int scan[8][8] = {
  110.   {0, 1, 5, 6, 14, 15, 27, 28},
  111.   {2, 4, 7, 13, 16, 26, 29, 42},
  112.   {3, 8, 12, 17, 25, 30, 41, 43},
  113.   {9, 11, 18, 24, 31, 40, 44, 53},
  114.   {10, 19, 23, 32, 39, 45, 52, 54},
  115.   {20, 22, 33, 38, 46, 51, 55, 60},
  116.   {21, 34, 37, 47, 50, 56, 59, 61},
  117.   {35, 36, 48, 49, 57, 58, 62, 63}};
  118.  
  119. const char *VidRate[16]={"forbidden","23.976 frames/sec","24 frames/sec","25 frames/sec",
  120.   "29.97 frames/sec","30 frames/sec","50 frames/sec","59.94 frames/sec","60 frames/sec",
  121.   "reserved","reserved","reserved","reserved","reserved","reserved","reserved"};
  122. const double VidRateNum[16]={1.0, 23.976, 24.0, 25.0, 29.97, 30.0, 50.0 ,59.94, 60.0,
  123.   1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
  124.  
  125. const char *PelRatio[16]={"forbidden","1 (VGA)","0.6735","0.7031 (16:9 625 lines)",
  126.   "0.7615","0.8055","0.8437 (16:9 525 lines)","0.8935","0.9375 (CCIR 601, 625 lines)",
  127.   "0.9815","1.0255","1.0695","1.1250 (CCIR 601, 525 lines)","1.1575","1.2015","reserved"};
  128.  
  129. /*
  130.  * We use a lookup table to make sure values stay in the 0..255 range.
  131.  * Since this is cropping (ie, x = (x < 0)?0:(x>255)?255:x; ), wee call this
  132.  * table the "crop table".
  133.  * MAX_NEG_CROP is the maximum neg/pos value we can handle.
  134.  */
  135.  
  136. #define MAX_NEG_CROP 384
  137. #define NUM_CROP_ENTRIES (256+2*MAX_NEG_CROP)
  138. static unsigned char cropTbl[NUM_CROP_ENTRIES];
  139.  
  140. extern int ditherType;
  141. char *ditherFlags;
  142.  
  143. /* Declare global pointer to vid stream used for current decoding. */
  144.  
  145. VidStream *curVidStream = NULL;
  146.  
  147. /* Max lum, chrom indices for illegal block checking. */
  148.  
  149. static int lmaxx;
  150. static int lmaxy;
  151. static int cmaxx;
  152. static int cmaxy;
  153.  
  154. /* Error Handling Code */
  155. char *errorLocation;
  156. char *errorSpecifics;
  157.  
  158. /* DCT printing code */
  159. char *dctSpecifics;
  160.  
  161. /* Boolean to keep track whether f_codes are within constrained params. */
  162. BOOLEAN f_code_ok=TRUE;
  163.  
  164. /* Statistics Decls */
  165.  
  166. unsigned int bitCount = 0;
  167.  
  168. unsigned int pictureSizeCount;
  169. unsigned int mbSizeCount;
  170. unsigned int *mbCBPPtr, *mbCoeffPtr, *mbSizePtr;
  171.  
  172. Statval stat_a[4];
  173.  
  174. /* Rate Measuring values */
  175. int rate_vals[60],rate_ptr=0,rate_sum=0,rate_started=0;
  176. int rate_disp,rate_init=FALSE,rate_max=0,rate_min=0xFFFFFFF;
  177.  
  178.  
  179. /* Keep track of block (Statistics) information */
  180. BlockVals blks;
  181.  
  182. double realTimeStart;
  183. int totNumFrames = 0;
  184.  
  185. /*
  186.  *--------------------------------------------------------------
  187.  *
  188.  * NewVidStream --
  189.  *
  190.  *    Allocates and initializes a VidStream structure. Takes
  191.  *      as parameter requested size for buffer length.
  192.  *
  193.  * Results:
  194.  *    A pointer to the new VidStream structure.
  195.  *
  196.  * Side effects:
  197.  *      None.
  198.  *
  199.  *--------------------------------------------------------------
  200.  */
  201.  
  202. VidStream *
  203. NewVidStream(bufLength)
  204.   int bufLength;
  205. {
  206.   int i, j;
  207.   VidStream *new;
  208.   static unsigned char default_intra_matrix[64] = {
  209.     8, 16, 19, 22, 26, 27, 29, 34,
  210.     16, 16, 22, 24, 27, 29, 34, 37,
  211.     19, 22, 26, 27, 29, 34, 34, 38,
  212.     22, 22, 26, 27, 29, 34, 37, 40,
  213.     22, 26, 27, 29, 32, 35, 40, 48,
  214.     26, 27, 29, 32, 35, 40, 48, 58,
  215.     26, 27, 29, 34, 38, 46, 56, 69,
  216.     27, 29, 35, 38, 46, 56, 69, 83};
  217.  
  218.   /* Check for legal buffer length. */
  219.  
  220.   if (bufLength < 4)
  221.     return NULL;
  222.  
  223.   /* Make buffer length multiple of 4. */
  224.  
  225.   bufLength = (bufLength + 3) >> 2;
  226.  
  227.   /* Allocate memory for new structure. */
  228.  
  229.   new = (VidStream *) malloc(sizeof(VidStream));
  230.   if (new == NULL)
  231.     return NULL;
  232.  
  233.   /* Initialize pointers to extension and user data. */
  234.  
  235.   new->group.ext_data = new->group.user_data =
  236.     new->picture.extra_info = new->picture.user_data =
  237.     new->picture.ext_data = new->slice.extra_info =
  238.     new->ext_data = new->user_data = NULL;
  239.  
  240.   /* Initialize stuff for GOP checking and display */
  241.   
  242.   new->group.code_types = (char *) malloc(MAX_CODE_TYPES);
  243.   if (new->group.code_types == NULL)
  244.     return NULL;
  245.   
  246.   new->group.max_code_types = MAX_CODE_TYPES;
  247.   new->group.picture_count = 0;
  248.  
  249.   /* Copy default intra matrix. */
  250.  
  251.   for (i = 0; i < 8; i++) {
  252.     for (j = 0; j < 8; j++) {
  253.       new->intra_quant_matrix[j][i] = default_intra_matrix[i * 8 + j];
  254.     }
  255.   }
  256.  
  257.   /* Initialize crop table. */
  258.  
  259.   for (i = (-MAX_NEG_CROP); i < NUM_CROP_ENTRIES - MAX_NEG_CROP; i++) {
  260.     if (i <= 0) {
  261.       cropTbl[i + MAX_NEG_CROP] = 0;
  262.     } else if (i >= 255) {
  263.       cropTbl[i + MAX_NEG_CROP] = 255;
  264.     } else {
  265.       cropTbl[i + MAX_NEG_CROP] = i;
  266.     }
  267.   }
  268.  
  269.   /* Initialize non intra quantization matrix. */
  270.  
  271.   for (i = 0; i < 8; i++) {
  272.     for (j = 0; j < 8; j++) {
  273.       new->non_intra_quant_matrix[j][i] = 16;
  274.     }
  275.   }
  276.  
  277.   /* Initialize pointers to image spaces. */
  278.  
  279.   new->current = new->past = new->future = NULL;
  280.   for (i = 0; i < RING_BUF_SIZE; i++) {
  281.     new->ring[i] = NULL;
  282.   }
  283.  
  284.   /* Create buffer. */
  285.  
  286.   new->buf_start = (unsigned int *) malloc(bufLength * 4);
  287.   if (new->buf_start == NULL)
  288.     return NULL;
  289.  
  290.   /*
  291.    * Set max_buf_length to one less than actual length to deal with messy
  292.    * data without proper seq. end codes.
  293.    */
  294.  
  295.   new->max_buf_length = bufLength - 1;
  296.  
  297.   /* Initialize bitstream i/o fields. */
  298.  
  299.   new->bit_offset = 0;
  300.   new->buf_length = 0;
  301.   new->buffer = new->buf_start;
  302.  
  303.  
  304.   /* Return structure. */
  305.  
  306.   return new;
  307. }
  308.  
  309.  
  310.  
  311. /*
  312.  *--------------------------------------------------------------
  313.  *
  314.  * DestroyVidStream --
  315.  *
  316.  *    Deallocates a VidStream structure.
  317.  *
  318.  * Results:
  319.  *      None.
  320.  *
  321.  * Side effects:
  322.  *    None.
  323.  *
  324.  *--------------------------------------------------------------
  325.  */
  326. void
  327. DestroyVidStream(astream)
  328.   VidStream *astream;
  329. {
  330.   int i;
  331.  
  332.   if (astream->ext_data != NULL)
  333.     free(astream->ext_data);
  334.  
  335.   if (astream->user_data != NULL)
  336.     free(astream->user_data);
  337.  
  338.   if (astream->group.ext_data != NULL)
  339.     free(astream->group.ext_data);
  340.  
  341.   if (astream->group.user_data != NULL)
  342.     free(astream->group.user_data);
  343.  
  344.   if (astream->picture.extra_info != NULL)
  345.     free(astream->picture.extra_info);
  346.  
  347.   if (astream->picture.ext_data != NULL)
  348.     free(astream->picture.ext_data);
  349.  
  350.   if (astream->picture.user_data != NULL)
  351.     free(astream->picture.user_data);
  352.  
  353.   if (astream->slice.extra_info != NULL)
  354.     free(astream->slice.extra_info);
  355.  
  356.   if (astream->buf_start != NULL)
  357.     free(astream->buf_start);
  358.  
  359.   for (i = 0; i < RING_BUF_SIZE; i++) {
  360.     if (astream->ring[i] != NULL) {
  361.       DestroyPictImage(astream->ring[i]);
  362.       astream->ring[i] = NULL;
  363.     }
  364.   }
  365.  
  366.   free((char *) astream);
  367. }
  368.  
  369.  
  370.  
  371.  
  372. /*
  373.  *--------------------------------------------------------------
  374.  *
  375.  * NewPictImage --
  376.  *
  377.  *    Allocates and initializes a PictImage structure.
  378.  *      The width and height of the image space are passed in
  379.  *      as parameters.
  380.  *
  381.  * Results:
  382.  *    A pointer to the new PictImage structure.
  383.  *
  384.  * Side effects:
  385.  *    None.
  386.  *
  387.  *--------------------------------------------------------------
  388.  */
  389.  
  390. PictImage *
  391. NewPictImage(width, height)
  392.   unsigned int width, height;
  393. {
  394.   PictImage *new;
  395.  
  396.   /* Allocate memory space for new structure. */
  397.  
  398.   new = (PictImage *) malloc(sizeof(PictImage));
  399.  
  400.  
  401.   /* Allocate memory for image spaces. */
  402.  
  403.   new->display = (unsigned char *) malloc(width * height);
  404.  
  405.   new->luminance = (unsigned char *) malloc(width * height);
  406.   new->Cr = (unsigned char *) malloc(width * height / 4);
  407.   new->Cb = (unsigned char *) malloc(width * height / 4);
  408.  
  409.   /* Reset locked flag. */
  410.  
  411.   new->locked = 0;
  412.  
  413.   /* Return pointer to new structure. */
  414.  
  415.   return new;
  416. }
  417.  
  418.  
  419.  
  420. /*
  421.  *--------------------------------------------------------------
  422.  *
  423.  * DestroyPictImage --
  424.  *
  425.  *    Deallocates a PictImage structure.
  426.  *
  427.  * Results:
  428.  *      None.
  429.  *
  430.  * Side effects:
  431.  *    None.
  432.  *
  433.  *--------------------------------------------------------------
  434.  */
  435. void
  436. DestroyPictImage(apictimage)
  437.   PictImage *apictimage;
  438. {
  439.   if (apictimage->luminance != NULL) {
  440.     free(apictimage->luminance);
  441.   }
  442.   if (apictimage->Cr != NULL) {
  443.     free(apictimage->Cr);
  444.   }
  445.   if (apictimage->Cb != NULL) {
  446.     free(apictimage->Cb);
  447.   }
  448.  
  449.   if (apictimage->display != NULL) {
  450.     free(apictimage->display);
  451.   }
  452.   free(apictimage);
  453. }
  454.  
  455.  
  456.  
  457. /*
  458.  *--------------------------------------------------------------
  459.  *
  460.  * mpegVidRsrc --
  461.  *
  462.  *      Parses bit stream until MB_QUANTUM number of
  463.  *      macroblocks have been decoded or current slice or
  464.  *      picture ends, whichever comes first. If the start
  465.  *      of a frame is encountered, the frame is time stamped
  466.  *      with the value passed in time_stamp. If the value
  467.  *      passed in buffer is not null, the video stream buffer
  468.  *      is set to buffer and the length of the buffer is
  469.  *      expected in value passed in through length. The current
  470.  *      video stream is set to vid_stream. If vid_stream
  471.  *      is passed as NULL, a new VidStream structure is created
  472.  *      and initialized and used as the current video stream.
  473.  *
  474.  * Results:
  475.  *      A pointer to the video stream structure used.
  476.  *
  477.  * Side effects:
  478.  *      Bit stream is irreversibly parsed. If a picture is completed,
  479.  *      a function is called to display the frame at the correct time.
  480.  *
  481.  *--------------------------------------------------------------
  482.  */
  483.  
  484. VidStream *
  485. mpegVidRsrc(time_stamp, vid_stream)
  486.   TimeStamp time_stamp;
  487.   VidStream *vid_stream;
  488. {
  489.   unsigned int data;
  490.   int i, status;
  491.  
  492.   /* Setup error specifics */
  493.   errorSpecifics=malloc(100);
  494.   *errorSpecifics='\0';
  495.   dctSpecifics=malloc(4000);
  496.   *dctSpecifics='\0';
  497.  
  498.   /* If vid_stream is null, create new VidStream structure. */
  499.  
  500.   if (vid_stream == NULL) {
  501.     return NULL;
  502.   }
  503.   /*
  504.    * Set global curVidStream to vid_stream. Necessary because bit i/o use
  505.    * curVidStream and are not passed vid_stream. Also set global bitstream
  506.    * parameters.
  507.    */
  508.  
  509.   curVidStream = vid_stream;
  510.   bitOffset = curVidStream->bit_offset;
  511. #ifdef UTIL2
  512.   curBits = *curVidStream->buffer << bitOffset;
  513. #else
  514.   curBits = *curVidStream->buffer;
  515. #endif
  516.   bufLength = curVidStream->buf_length;
  517.   bitBuffer = curVidStream->buffer;
  518.  
  519.   next_start_code();
  520.   show_bits32(data);
  521.   if (data != SEQ_START_CODE) {
  522.     fprintf(stderr, "This is not an MPEG stream.\n");
  523.     DestroyVidStream(curVidStream);
  524.     exit(1);
  525.   }
  526.   
  527.   /*
  528.    * Process according to start code (or parse macroblock if not a start code
  529.    * at all.
  530.    */
  531.   
  532.   while (1) { 
  533.   start:
  534.     show_bits32(data);
  535.     switch (data) {
  536.  
  537.     case SEQ_END_CODE:
  538.     case 0x000001b9:   /*  handle ISO_11172_END_CODE too */
  539.       /* Print last gop. */
  540.       PrintGOP(vid_stream);
  541.     
  542.       /* Display last frame. */
  543.       if (vid_stream->future != NULL) {
  544.     vid_stream->current = vid_stream->future;
  545.       }
  546.       
  547.       /* Sequence done. Do the right thing. For right now, exit. */
  548.       
  549.       
  550.       PrintAllStats(); 
  551.       PrintTimeInfo(); 
  552.       
  553.       DestroyVidStream(curVidStream);
  554.       exit(0);
  555.       break;
  556.       
  557.     case SEQ_START_CODE:
  558.       
  559.       /* Sequence start code. Parse sequence header. */
  560.       if (opts&COLLECTING&OFFS_INFO) {
  561.     fprintf(offs_fp,"sequence %d\n",bitCountRead());
  562.       }
  563.       
  564.       if (ParseSeqHead(vid_stream) != PARSE_OK) {
  565.     errorLocation="Sequence Header";
  566.     goto error;
  567.       }
  568.       
  569.       /*
  570.        * Return after sequence start code so that application above can use
  571.        * info in header.
  572.        */
  573.       
  574.       break;
  575.       
  576.     case GOP_START_CODE:
  577.  
  578.       /* Group of Pictures start code.*/
  579.       /* Print previous gop.  (For the first GOP, the function does nothing.) */
  580.       PrintGOP(vid_stream);
  581.       
  582.       if (opts&COLLECTING&OFFS_INFO) {
  583.         fprintf(offs_fp,"gop %d\n",bitCountRead());
  584.       }
  585.       
  586.       /* Parse GOP Header */
  587.       if (ParseGOP(vid_stream) != PARSE_OK) {
  588.         errorLocation="Group of Pictures";
  589.         goto error;
  590.       }
  591.  
  592.       break;
  593.  
  594.     case PICTURE_START_CODE:
  595.       
  596.       /* Picture start code. Parse picture header and first slice header. */
  597.       
  598.       status = ParsePicture(vid_stream, time_stamp);
  599.       
  600.       if (status == SKIP_PICTURE) {
  601.     next_start_code();
  602.     while (!next_bits(32, PICTURE_START_CODE)) {
  603.       if (next_bits(32, GOP_START_CODE))
  604.         break;
  605.       else if (next_bits(32, SEQ_END_CODE))
  606.         break;
  607.       flush_bits(24);
  608.       next_start_code();
  609.     }
  610.     break;
  611.       } else if (status != PARSE_OK) {
  612.     errorLocation="Picture";
  613.     goto error;
  614.       }
  615.       
  616.       if (ParseSlice(vid_stream) != PARSE_OK) {
  617.     errorLocation="Slice (1)";
  618.     goto error;
  619.       }
  620.       break;
  621.       
  622.     default:
  623.       
  624.       /* Check for slice start code. */
  625.       
  626.       if ((data >= SLICE_MIN_START_CODE) && (data <= SLICE_MAX_START_CODE)) {
  627.     
  628.     /* Slice start code. Parse slice header. */
  629.     
  630.     if (ParseSlice(vid_stream) != PARSE_OK) {
  631.       errorLocation="Slice (2)";
  632.       goto error;
  633.     }
  634.       } else {
  635.     if ((unsigned int) (data & 0xfffffe00)== (unsigned int )0) {
  636.       /* Wasn't any valid start code for MPEG-1 video streams */
  637.       fprintf(stderr,"Invalid start code, perhaps MPEG-2 file?\n");
  638.       exit(1);
  639.     }
  640.       }
  641.       /* Parse until next bits are start code */
  642.       
  643.       do {
  644.     if (ParseMacroBlock(vid_stream) != PARSE_OK) {
  645.       errorLocation="Macro block";
  646.       goto error;
  647.     }
  648.       } while (!next_bits(23, 0x00000000));
  649.       
  650.       next_start_code();
  651.       show_bits32(data);
  652.       
  653.       /*
  654.        * If start code is outside range of slice start codes, frame is
  655.        * complete, display frame.
  656.        */
  657.       
  658.       if ((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) {
  659.     EndTime();
  660.     stat_a[0].totsize += bitCountRead() - pictureSizeCount;
  661.     if (opts&SIZE_INFO&COLLECTING) {
  662.       fprintf(size_fp,"%d\t%c\t%8d\n",
  663.           blks.frame,"0IPB"[stat_a[0].frametype],stat_a[0].totsize);
  664.     }
  665.     if (COLLECTING&opts&RATE_INFO) {
  666.       rate_sum-=rate_vals[rate_ptr];
  667.       rate_vals[rate_ptr]=stat_a[0].totsize;
  668.       rate_sum+=stat_a[0].totsize;
  669.       if (rate_started) fprintf(rate_fp,"%d\n",rate_sum);
  670.       else if (rate_ptr==(rate_disp-1)) rate_started=TRUE;
  671.       if (rate_sum>rate_max) rate_max=rate_sum;
  672.       if (rate_sum<rate_min) rate_min=rate_sum;
  673.       rate_ptr= (rate_ptr+1)%rate_disp;
  674.     }
  675.     if (COLLECTING) CollectStats();
  676.     DoPictureDisplay(vid_stream);
  677.       }
  678.     }
  679.   }
  680.     
  681.  error:
  682.   /* "calling" routine must set errorLocation, errorSpecifics may be set */
  683.   fprintf(stderr, "Error!!!! while parsing %s in frame %d, skipping to start code.  %s\n",
  684.       errorLocation,blks.frame,errorSpecifics);
  685.   sprintf(errorSpecifics,"");
  686.   next_start_code();
  687.   goto start;
  688. }
  689.  
  690.  
  691.  
  692. /*
  693.  *--------------------------------------------------------------
  694.  *
  695.  * ParseSeqHead --
  696.  *
  697.  *      Assumes bit stream is at the begining of the sequence
  698.  *      header start code. Parses off the sequence header.
  699.  *
  700.  * Results:
  701.  *      Fills the vid_stream structure with values derived and
  702.  *      decoded from the sequence header. Allocates the pict image
  703.  *      structures based on the dimensions of the image space
  704.  *      found in the sequence header.
  705.  *
  706.  * Side effects:
  707.  *      Bit stream irreversibly parsed off.
  708.  *
  709.  *--------------------------------------------------------------
  710.  */
  711.  
  712. static int
  713. ParseSeqHead(vid_stream)
  714.   VidStream *vid_stream;
  715. {
  716.  
  717.   unsigned int data;
  718.   int i;
  719.  
  720.   /* Flush off sequence start code. */
  721.   flush_bits32;
  722.  
  723.   /* Get horizontal size of image space. */
  724.   get_bits12(data);
  725.   vid_stream->h_size = data;
  726.  
  727.   /* Get vertical size of image space. */
  728.  
  729.   get_bits12(data);
  730.   vid_stream->v_size = data;
  731.  
  732.   /* Calculate macroblock width and height of image space. */
  733.  
  734.   vid_stream->mb_width = (vid_stream->h_size + 15) / 16;
  735.   vid_stream->mb_height = (vid_stream->v_size + 15) / 16;
  736.  
  737.   /* If dither type is MBORDERED allocate ditherFlags. */
  738.  
  739.   if (ditherType == MBORDERED_DITHER) {
  740.     ditherFlags = (char *) malloc(vid_stream->mb_width*vid_stream->mb_height);
  741.   }
  742.  
  743.   /* Initialize lmaxx, lmaxy, cmaxx, cmaxy. */
  744.  
  745.   lmaxx = vid_stream->mb_width*16-8;
  746.   lmaxy = vid_stream->mb_height*16-8;
  747.   cmaxx = vid_stream->mb_width*8-8;
  748.   cmaxy = vid_stream->mb_height*8-8;
  749.  
  750.   /*
  751.    * Initialize ring buffer of pict images now that dimensions of image space
  752.    * are known.
  753.    */
  754.  
  755.  
  756.   if (vid_stream->ring[0] == NULL) {
  757.     for (i = 0; i < RING_BUF_SIZE; i++) {
  758.       vid_stream->ring[i] = NewPictImage(vid_stream->mb_width * 16,
  759.                      vid_stream->mb_height * 16);
  760.     }
  761.   }
  762.  
  763.   /* Parse of aspect ratio code. */
  764.  
  765.   get_bits4(data);
  766.   vid_stream->aspect_ratio = (unsigned char) data;
  767.  
  768.   /* Parse off picture rate code. */
  769.  
  770.   get_bits4(data);
  771.   vid_stream->picture_rate = (unsigned char) data;
  772.   vid_stream->orig_picture_rate = (unsigned char) data;
  773.   if (VidRateNum[data] == 1.0) {
  774.     fprintf(stderr,
  775.         "Picture rate is invalid!  It is listed in Std as %s (code is %d)\n",
  776.         VidRate[data],data);
  777.     fprintf(stderr,
  778.         "Any average dependent on the picture rate will be incorrect\n");
  779.     fprintf(stderr,"\t(assumed to mean 30fps).  Probably a Xing sequence.\n\n");
  780.     vid_stream->picture_rate=5;
  781.   }
  782.   if (opts&RATE_INFO) {
  783.     /* Setup data rate collection structures */
  784.     if (!rate_init) {
  785.       if (opts&RATE_LENGTH_SET)
  786.     rate_disp=rate_frames;
  787.       else rate_disp=(int)(VidRateNum[data]+0.5);
  788.       rate_ptr=0; rate_started=FALSE; rate_init=TRUE;
  789.       for(i=0; i<rate_disp;i++) rate_vals[i]=0;
  790.       rate_sum=0;
  791.     } else if ((int)(VidRateNum[data]+0.5)!=rate_disp) {
  792.     fprintf(rate_fp,"CHANGE in picture rate from %d to %d\n",
  793.         (int)(VidRateNum[data]+0.5),rate_disp);
  794.       }
  795.   }
  796.  
  797.   /* Parse off bit rate. */
  798.   get_bits18(data);
  799.   vid_stream->bit_rate = data;
  800.   
  801.   /* Flush marker bit. */
  802.   flush_bits(1);
  803.  
  804.   /* Parse off vbv buffer size. */
  805.   get_bits10(data);
  806.   vid_stream->vbv_buffer_size = data;
  807.  
  808.   if (data*1024>vid_stream->max_buf_length) {
  809.     unsigned int *newbuf;
  810.     int sz=1024*data+1;
  811.     /* If they actually want a bigger buffer than we default to,
  812.        let them have it! (if we can) */
  813.     newbuf = (unsigned int *) realloc((char *)vid_stream->buf_start,4*sz);
  814.     if (newbuf!=(unsigned int *)NULL) {
  815.       vid_stream->max_buf_length=sz;
  816.       bitBuffer=(bitBuffer-vid_stream->buf_start)+newbuf;
  817.       vid_stream->buf_start=newbuf;
  818.     }}
  819.  
  820.   /* Parse off constrained parameter flag. */
  821.   get_bits1(data);
  822.   if (data) {
  823.     vid_stream->const_param_flag = TRUE;
  824.   } else
  825.     vid_stream->const_param_flag = FALSE;
  826.  
  827.   /*
  828.    * If intra_quant_matrix_flag set, parse off intra quant matrix values.
  829.    */
  830.   get_bits1(data);
  831.   if (data) {
  832.     int new_table=FALSE;
  833.     for (i = 0; i < 64; i++) {
  834.       get_bits8(data);
  835.       new_table = new_table ||
  836.     (vid_stream->intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] !=
  837.      (unsigned char) data);
  838.       vid_stream->intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] =
  839.     (unsigned char) data;
  840.     }
  841.     if (opts&QSCALE_INFO) {
  842.       PrintQT(qscale_fp,"IQ",new_table,(unsigned char *)vid_stream->intra_quant_matrix);
  843.     }
  844.     if ((opts&LOUD) || new_table) {
  845.       PrintQT(stdout,"IQ",new_table,(unsigned char *)vid_stream->intra_quant_matrix);
  846.     }
  847.   }
  848.  
  849.   /*
  850.    * If non intra quant matrix flag set, parse off non intra quant matrix
  851.    * values.
  852.    */
  853.  
  854.   get_bits1(data);
  855.   if (data) {
  856.     int new_table=FALSE;
  857.     for (i = 0; i < 64; i++) {
  858.       get_bits8(data);
  859.       new_table = new_table ||
  860.     (vid_stream->non_intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] !=
  861.      (unsigned char) data);
  862.       vid_stream->non_intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] =
  863.     (unsigned char) data;
  864.     }
  865.     if (opts&QSCALE_INFO) {
  866.       PrintQT(qscale_fp,"NIQ",new_table,(unsigned char *)vid_stream->non_intra_quant_matrix);
  867.     }
  868.     if ((opts&LOUD) || new_table) {
  869.       PrintQT(stdout,"NIQ",new_table,(unsigned char *)vid_stream->non_intra_quant_matrix);
  870.     }
  871.   }
  872.  
  873.   next_start_code();
  874.  
  875.   /*
  876.    * If next start code is extension start code, parse off extension data.
  877.    */
  878.  
  879.   if (next_bits(32, EXT_START_CODE)) {
  880.     int sz;
  881.     flush_bits32;
  882.     if (vid_stream->ext_data != NULL) {
  883.       free(vid_stream->ext_data);
  884.       vid_stream->ext_data = NULL;
  885.     }
  886.     vid_stream->ext_data = get_ext_data(&sz);
  887.     vid_stream->ext_size = sz;
  888.   }
  889.   /* If next start code is user start code, parse off user data. */
  890.  
  891.   if (next_bits(32, USER_START_CODE)) {
  892.     int sz;
  893.     flush_bits32;
  894.     if (vid_stream->user_data != NULL) {
  895.       free(vid_stream->user_data);
  896.       vid_stream->user_data = NULL;
  897.     }
  898.     vid_stream->user_data = get_ext_data(&sz);
  899.     vid_stream->user_size = sz;
  900.     if (sz > 0 && opts&COLLECTING&USERDAT_INFO) {
  901.       fprintf(userdat_fp, "Sequence Header user data:\n");
  902.       print_binary(userdat_fp, vid_stream->user_data, vid_stream->user_size);
  903.     }
  904.   }
  905.   return PARSE_OK;
  906. }
  907.  
  908.  
  909.  
  910. /*
  911.  *--------------------------------------------------------------
  912.  *
  913.  * ParseGOP --
  914.  *
  915.  *      Parses of group of pictures header from bit stream
  916.  *      associated with vid_stream.
  917.  *
  918.  * Results:
  919.  *      Values in gop header placed into video stream structure.
  920.  *
  921.  * Side effects:
  922.  *      Bit stream irreversibly parsed.
  923.  *
  924.  *--------------------------------------------------------------
  925.  */
  926.  
  927. static int
  928. ParseGOP(vid_stream)
  929.   VidStream *vid_stream;
  930. {
  931.   unsigned int data;
  932.  
  933.   /* Reset stuff for GOP checking */
  934.   vid_stream->group.picture_count = 0;
  935.   memset(vid_stream->group.code_types, 0, vid_stream->group.max_code_types);
  936.  
  937.  
  938.   /* Flush group of pictures start code. WWWWWWOOOOOOOSSSSSSHHHHH!!! */
  939.  
  940.   flush_bits32;
  941.  
  942.   /* Parse off drop frame flag. */
  943.  
  944.   get_bits1(data);
  945.   if (data) {
  946.     vid_stream->group.drop_flag = TRUE;
  947.   } else
  948.     vid_stream->group.drop_flag = FALSE;
  949.  
  950.   /* Parse off hour component of time code. */
  951.  
  952.   get_bits5(data);
  953.   vid_stream->group.tc_hours = data;
  954.  
  955.   /* Parse off minute component of time code. */
  956.  
  957.   get_bits6(data);
  958.   vid_stream->group.tc_minutes = data;
  959.  
  960.   /* Flush marker bit. */
  961.  
  962.   flush_bits(1);
  963.  
  964.   /* Parse off second component of time code. */
  965.  
  966.   get_bits6(data);
  967.   vid_stream->group.tc_seconds = data;
  968.  
  969.   /* Parse off picture count component of time code. */
  970.  
  971.   get_bits6(data);
  972.   vid_stream->group.tc_pictures = data;
  973.  
  974.   /* Parse off closed gop and broken link flags. */
  975.  
  976.   get_bits2(data);
  977.   if (data > 1) {
  978.     vid_stream->group.closed_gop = TRUE;
  979.     if (data > 2) {
  980.       vid_stream->group.broken_link = TRUE;
  981.     } else
  982.       vid_stream->group.broken_link = FALSE;
  983.   } else {
  984.     vid_stream->group.closed_gop = FALSE;
  985.     if (data) {
  986.       vid_stream->group.broken_link = TRUE;
  987.     } else
  988.       vid_stream->group.broken_link = FALSE;
  989.   }
  990.  
  991.   if (opts&COLLECTING&BLOCK_INFO) {
  992.     fprintf(block_fp,"gop %c %c\n",
  993.         vid_stream->group.closed_gop ? 'C' : 'O',
  994.         vid_stream->group.broken_link ? 'B': 'W');
  995.   }
  996.   
  997.  
  998.   /* Goto next start code. */
  999.  
  1000.   next_start_code();
  1001.  
  1002.   /* If next start code is extension data, parse off extension data. */
  1003.  
  1004.   if (next_bits(32, EXT_START_CODE)) {
  1005.     flush_bits32;
  1006.     if (vid_stream->group.ext_data != NULL) {
  1007.       free(vid_stream->group.ext_data);
  1008.       vid_stream->group.ext_data = NULL;
  1009.     }
  1010.     vid_stream->group.ext_data = get_ext_data(&vid_stream->group.ext_size);
  1011.   }
  1012.   /* If next start code is user data, parse off user data. */
  1013.  
  1014.   if (next_bits(32, USER_START_CODE)) {
  1015.     flush_bits32;
  1016.     if (vid_stream->group.user_data != NULL) {
  1017.       free(vid_stream->group.user_data);
  1018.       vid_stream->group.user_data = NULL;
  1019.     }
  1020.     vid_stream->group.user_data = get_ext_data(&vid_stream->group.user_size);
  1021.     if ( vid_stream->group.user_size > 0 && opts&COLLECTING&USERDAT_INFO) {
  1022.       fprintf(userdat_fp, "GOP Header user data:\n");
  1023.       print_binary(userdat_fp, vid_stream->user_data, vid_stream->user_size);
  1024.     }
  1025.   }
  1026.  
  1027.   return PARSE_OK;
  1028. }
  1029.  
  1030.  
  1031. /*
  1032.  *--------------------------------------------------------------
  1033.  *
  1034.  * PrintGOP --
  1035.  *
  1036.  *      Prints picture_coding_types for a group of pictures with some 
  1037.  *      limited error checking on the temporal references.
  1038.  *
  1039.  * Results:
  1040.  *      Printed to stdout.
  1041.  *
  1042.  * Side effects:
  1043.  *      None.
  1044.  *
  1045.  *--------------------------------------------------------------
  1046.  */
  1047.  
  1048. static void
  1049. PrintGOP(vid_stream)
  1050.   VidStream *vid_stream;
  1051. {
  1052.   int i, c, do_print;
  1053.  
  1054.   /* If this is the first GOP, do nothing.  (Empty GOPs will go undetected.) */
  1055.   if (vid_stream->group.picture_count == 0) return;
  1056.  
  1057.   do_print = opts & COLLECTING & LOUD;
  1058.  
  1059.   if (do_print) printf(" / ");
  1060.   for (i = 0; i < vid_stream->group.picture_count; i++) {
  1061.     /* Guard against accessing beyond end of code_types[] */
  1062.     if (i == vid_stream->group.max_code_types) break;
  1063.  
  1064.     switch (vid_stream->group.code_types[i]) {
  1065.     case I_TYPE:
  1066.       c = 'I';
  1067.       break;
  1068.     case P_TYPE:
  1069.       c = 'P';
  1070.       break;
  1071.     case B_TYPE:
  1072.       c = 'B';
  1073.       break;
  1074.     case D_TYPE:
  1075.       c = 'D';
  1076.       break;
  1077.     case SKIP_P_TYPE:
  1078.     case SKIP_B_TYPE:
  1079.       c = '-';
  1080.       break;
  1081.     case 0:
  1082.       /* The output will be ugly if there is an error. */
  1083.       fprintf(stderr, "\nError: temporal_reference %d missing from GOP\n", i);
  1084.       /* no break */
  1085.     default:
  1086.       c = '?';
  1087.       break;
  1088.     }
  1089.     if (do_print) printf("%c", c);
  1090.   }
  1091.   if (do_print) printf("\n");
  1092.  
  1093.   /* check for Property 2 in D.5.2 of 11172-2 */
  1094.   switch (vid_stream->group.code_types[0]) {
  1095.   case I_TYPE:
  1096.   case B_TYPE:
  1097.   case SKIP_B_TYPE:
  1098.     break;
  1099.   default:
  1100.     fprintf(stderr, "\nError: first picture of GOP in display order must be I or B\n");
  1101.   }
  1102.  
  1103.   switch (vid_stream->group.code_types[i - 1]) {
  1104.   case I_TYPE:
  1105.   case P_TYPE:
  1106.     break;
  1107.   default:
  1108.     /* This message may be bogus if GOP size was too big. */
  1109.     fprintf(stderr, "\nError: last picture of GOP in display order must be I or P\n");
  1110.   }
  1111. }
  1112.  
  1113. /*
  1114.  *--------------------------------------------------------------
  1115.  *
  1116.  * ParsePicture --
  1117.  *
  1118.  *      Parses picture header. Marks picture to be presented
  1119.  *      at particular time given a time stamp.
  1120.  *
  1121.  * Results:
  1122.  *      Values from picture header put into video stream structure.
  1123.  *
  1124.  * Side effects:
  1125.  *      Bit stream irreversibly parsed.
  1126.  *
  1127.  *--------------------------------------------------------------
  1128.  */
  1129.  
  1130. static int
  1131. ParsePicture(vid_stream, time_stamp)
  1132. VidStream *vid_stream;
  1133.   TimeStamp time_stamp;
  1134. {
  1135.   unsigned int data;
  1136.   int i;
  1137.   static int last_bit_count=0;
  1138. #ifdef doesntwork
  1139.   static int vbv_size=0;
  1140.   static double vbv_delay=0.0;
  1141. #endif
  1142.  
  1143.   /* Flush header start code. */
  1144.   flush_bits32;
  1145.  
  1146.   /* Parse off temporal reference. */
  1147.   get_bits10(data);
  1148.   vid_stream->picture.temp_ref = data;
  1149.  
  1150.   /* Parse of picture type. */
  1151.   get_bits3(data);
  1152.   if (data < I_TYPE || data > D_TYPE) {
  1153.     fprintf(stderr, "\nError: picture_coding_type is forbidden or reserved (frame %d, type %d)\n",
  1154.         blks.frame+1,data);
  1155.   } else if (vid_stream->group.picture_count == 0 && data != I_TYPE) {
  1156.     fprintf(stderr, "\nError: First picture of GOP in bitstream order must be I\n");
  1157.   }
  1158.   vid_stream->picture.code_type = data;
  1159.  
  1160.   if (vid_stream->group.picture_count < vid_stream->group.max_code_types) {
  1161.     if (vid_stream->group.code_types[vid_stream->picture.temp_ref] == 0) {
  1162.       /* Out-of-order temporal_references are currently not detected */
  1163.       vid_stream->group.code_types[vid_stream->picture.temp_ref] =
  1164.     vid_stream->picture.code_type;
  1165.     } else {
  1166.       fprintf(stderr, "\nError: temporal reference %d duplicated in GOP\n",
  1167.           vid_stream->picture.temp_ref);
  1168.       /*
  1169.        * TODO: this is actually legal for GOP size >= 1024, since
  1170.        * temporal_reference is a modulo 1024 number.  (See 11172-2  2.4.3.4)
  1171.        */
  1172.     }
  1173.   } else if (vid_stream->group.picture_count == vid_stream->group.max_code_types) {
  1174.     /* Only print this message once */
  1175.     fprintf(stderr, "\nWarning: GOP size bigger than I can check\n");
  1176.     /*
  1177.      * TODO: could realloc & increase max_code_types, but would also need
  1178.      * to handle temporal_reference values being reused.
  1179.      */
  1180.   }
  1181.  
  1182.  
  1183.   /* Parse off vbv buffer delay value. */
  1184.   get_bits16(data);
  1185.   vid_stream->picture.vbv_delay = data;
  1186.  
  1187. #ifdef doesntwork
  1188.    Unfortunately, vbv_delay > picture_delay a lot, so this doesnt work at all.
  1189.    Need to be rethought out.
  1190.  
  1191.   {  /* Check out VBV Buffer fullness */
  1192. /*    static int last_bit_count=0, vbv_size=0, vbv_delay=0;*/
  1193.     static int rate = -1;
  1194.     static int buffer_size;
  1195.     static double picture_delay;
  1196.  
  1197.     if (rate == -1) {
  1198.       rate = vid_stream->bit_rate * 400;
  1199.       buffer_size = vid_stream->vbv_buffer_size*16*1024;
  1200.       picture_delay = (1.0/VidRateNum[vid_stream->picture_rate]);
  1201.       /* Dont do anything at first picture */
  1202.     } else {
  1203.       vbv_size += rate * vbv_delay;
  1204.       if (vbv_size > buffer_size) {
  1205.     fprintf(stderr,"VBV overflow at frame %d (%d > %d bits)\n",
  1206.         blks.frame, vbv_size, buffer_size);
  1207.       } 
  1208.       vbv_size -= (bitCountRead() - last_bit_count);
  1209.       if (vbv_size < 0) {
  1210.     fprintf(stderr,"VBV underflow at frame %d (%d < 0 bits)\n",
  1211.         blks.frame, vbv_size);
  1212.       } 
  1213.       if (picture_delay < vbv_delay) {
  1214.     fprintf(stderr,"Yikes, vbv_delay > one frame time! (%g < %g)\n",
  1215.         picture_delay,vbv_delay);
  1216.       }
  1217.       vbv_size += rate * (picture_delay = vbv_delay);  /* add in missed time */
  1218.       vbv_delay = data / 90000.0;
  1219.     }
  1220.   }
  1221. #endif
  1222.  
  1223.   blks.frame++;
  1224.  
  1225.   if (START_F&opts) {
  1226.     COLLECTING = (blks.frame>=start_opt)?COLLECT_ON:COLLECT_OFF;
  1227.   } 
  1228.   if (opts&END_F) {
  1229.     if (blks.frame > end_opt) {
  1230.       PrintGOP(vid_stream);
  1231.       printf("Done Collecting!\n");
  1232.       PrintAllStats(); 
  1233.       PrintTimeInfo(); 
  1234.       DestroyVidStream(vid_stream);
  1235.       exit(0);
  1236.     }
  1237.   }
  1238.  
  1239.   vid_stream->group.picture_count++;
  1240.  
  1241.   /* echo frame type on screen */
  1242.   if (opts&COLLECTING&LOUD) printtype(vid_stream);
  1243.  
  1244.   if (opts&COLLECTING&OFFS_INFO) {
  1245.     fprintf(offs_fp,"picture %d (%d)\n",
  1246.         bitCountRead(),vid_stream->picture.temp_ref);
  1247.   }
  1248.  
  1249.   if ((vid_stream->picture.code_type == B_TYPE) &&
  1250.       ((vid_stream->future == NULL) ||
  1251.        ((vid_stream->past == NULL) && !(vid_stream->group.closed_gop)))) {
  1252.     /* According to 2-D.5.1 (p D-18) this is ok, if the refereneces are OK */
  1253.     last_bit_count = bitCountRead();
  1254.     vid_stream->group.code_types[vid_stream->picture.temp_ref] = SKIP_B_TYPE;
  1255.     return SKIP_PICTURE;
  1256.   }
  1257.   
  1258.   if ((vid_stream->picture.code_type == P_TYPE) &&
  1259.       (vid_stream->future == NULL)) {
  1260.     last_bit_count=bitCountRead();
  1261.     vid_stream->group.code_types[vid_stream->picture.temp_ref] = SKIP_P_TYPE;
  1262.     return SKIP_PICTURE;
  1263.   }
  1264.  
  1265.   StartTime();
  1266.   
  1267.   if (COLLECTING) {
  1268.     stat_a[0].frametype = vid_stream->picture.code_type;
  1269.     stat_a[0].totsize = 45;
  1270.     stat_a[0].number = 1;
  1271.     pictureSizeCount = bitCountRead();
  1272.     if (opts&COLLECTING&BLOCK_INFO) {
  1273.       blks.slice=0; blks.block=0;
  1274.       fprintf(block_fp,"frame %d %c %s\n", blks.frame,
  1275.           "0IPB"[stat_a[0].frametype],
  1276.           (vid_stream->picture.full_pel_forw_vector?"whole":"half"));
  1277.     }
  1278.   }
  1279.  
  1280.   /* If P or B type frame... */
  1281.  
  1282.   if ((vid_stream->picture.code_type == 2) || 
  1283.       (vid_stream->picture.code_type == 3)) {
  1284.  
  1285.     /* Parse off forward vector full pixel flag. */
  1286.     get_bits1(data);
  1287.     if (data)
  1288.       vid_stream->picture.full_pel_forw_vector = TRUE;
  1289.     else
  1290.       vid_stream->picture.full_pel_forw_vector = FALSE;
  1291.  
  1292.     /* Parse of forw_r_code. */
  1293.     get_bits3(data);
  1294.     f_code_ok &= (data <= 4);
  1295.  
  1296.     /* Decode forw_r_code into forw_r_size and forw_f. */
  1297.  
  1298.     vid_stream->picture.forw_r_size = data - 1;
  1299.     vid_stream->picture.forw_f = (1 << vid_stream->picture.forw_r_size);
  1300.   }
  1301.   /* If B type frame... */
  1302.  
  1303.   if (vid_stream->picture.code_type == 3) {
  1304.  
  1305.     /* Parse off back vector full pixel flag. */
  1306.     get_bits1(data);
  1307.     if (data)
  1308.       vid_stream->picture.full_pel_back_vector = TRUE;
  1309.     else
  1310.       vid_stream->picture.full_pel_back_vector = FALSE;
  1311.  
  1312.     /* Parse off back_r_code. */
  1313.     get_bits3(data);
  1314.     f_code_ok &= (data <= 4);
  1315.  
  1316.     /* Decode back_r_code into back_r_size and back_f. */
  1317.  
  1318.     vid_stream->picture.back_r_size = data - 1;
  1319.     vid_stream->picture.back_f = (1 << vid_stream->picture.back_r_size);
  1320.   }
  1321.   /* Get extra bit picture info. */
  1322.  
  1323.   if (vid_stream->picture.extra_info != NULL) {
  1324.     free(vid_stream->picture.extra_info);
  1325.     vid_stream->picture.extra_info = NULL;
  1326.   }
  1327.   vid_stream->picture.extra_info = get_extra_bit_info();
  1328.  
  1329.   /* Goto next start code. */
  1330.   next_start_code();
  1331.  
  1332.   /* If start code is extension start code, parse off extension data. */
  1333.  
  1334.   if (next_bits(32, EXT_START_CODE)) {
  1335.     flush_bits32;
  1336.  
  1337.     if (vid_stream->picture.ext_data != NULL) {
  1338.       free(vid_stream->picture.ext_data);
  1339.       vid_stream->picture.ext_data = NULL;
  1340.     }
  1341.     vid_stream->picture.ext_data = get_ext_data(&vid_stream->picture.ext_size);
  1342.   }
  1343.   /* If start code is user start code, parse off user data. */
  1344.  
  1345.   if (next_bits(32, USER_START_CODE)) {
  1346.     flush_bits32;
  1347.  
  1348.     if (vid_stream->picture.user_data != NULL) {
  1349.       free(vid_stream->picture.user_data);
  1350.       vid_stream->picture.user_data = NULL;
  1351.     }
  1352.     vid_stream->picture.user_data = get_ext_data(&vid_stream->picture.user_size);
  1353.     if ( vid_stream->group.user_size > 0 && opts&COLLECTING&USERDAT_INFO) {
  1354.       fprintf(userdat_fp, "Picture Header (%d) user data:\n", blks.frame);
  1355.       print_binary(userdat_fp, vid_stream->user_data, vid_stream->user_size);
  1356.     }
  1357.   }
  1358.   /* Find a pict image structure in ring buffer not currently locked. */
  1359.  
  1360.   i = 0;
  1361.  
  1362.   while (vid_stream->ring[i]->locked != 0) {
  1363.     if (++i >= RING_BUF_SIZE) {
  1364.       fprintf(stderr,"Fatal error. Ring buffer full.");
  1365.       exit(1);
  1366.     }
  1367.   }
  1368.  
  1369.   /* Set current pict image structure to the one just found in ring. */
  1370.  
  1371.   vid_stream->current = vid_stream->ring[i];
  1372.  
  1373.   /* Set time stamp. */
  1374.  
  1375.   vid_stream->current->show_time = time_stamp;
  1376.  
  1377.   /* Reset past macroblock address field. */
  1378.  
  1379.   vid_stream->mblock.past_mb_addr = -1;
  1380.  
  1381.   last_bit_count = bitCountRead();
  1382.   return PARSE_OK;
  1383. }
  1384.  
  1385.  
  1386.  
  1387. /*
  1388.  *--------------------------------------------------------------
  1389.  *
  1390.  * ParseSlice --
  1391.  *
  1392.  *      Parses off slice header.
  1393.  *
  1394.  * Results:
  1395.  *      Values found in slice header put into video stream structure.
  1396.  *
  1397.  * Side effects:
  1398.  *      Bit stream irreversibly parsed.
  1399.  *
  1400.  *--------------------------------------------------------------
  1401.  */
  1402.  
  1403. static int
  1404. ParseSlice(vid_stream)
  1405.   VidStream *vid_stream;
  1406. {
  1407.   unsigned int data;
  1408.  
  1409.   /* Flush slice start code. */
  1410.  
  1411.   flush_bits(24);
  1412.  
  1413.   /* Parse off slice vertical position. */
  1414.  
  1415.   get_bits8(data);
  1416.   vid_stream->slice.vert_pos = data;
  1417.  
  1418.   /* Parse off quantization scale. */
  1419.  
  1420.   get_bits5(data);
  1421.   vid_stream->slice.quant_scale = data;
  1422.   if (opts&COLLECTING&BLOCK_INFO) {
  1423.     blks.slice++;
  1424.     blks.qs=data;
  1425.     fprintf(block_fp,"slice %d %d\n",blks.slice,data);
  1426.   }
  1427.  
  1428.  
  1429.   if (opts&COLLECTING&OFFS_INFO) {
  1430.     fprintf(offs_fp,"slice %d (%d)\n",bitCountRead()-37,vid_stream->slice.vert_pos);
  1431.   }
  1432.  
  1433.   /* Parse off extra bit slice info. */
  1434.  
  1435.   if (vid_stream->slice.extra_info != NULL) {
  1436.     free(vid_stream->slice.extra_info);
  1437.     vid_stream->slice.extra_info = NULL;
  1438.   }
  1439.   vid_stream->slice.extra_info = get_extra_bit_info();
  1440.  
  1441.   /* Reset past intrablock address. */
  1442.  
  1443.   vid_stream->mblock.past_intra_addr = -2;
  1444.  
  1445.   /* Reset previous recon motion vectors. */
  1446.  
  1447.   vid_stream->mblock.recon_right_for_prev = 0;
  1448.   vid_stream->mblock.recon_down_for_prev = 0;
  1449.   vid_stream->mblock.recon_right_back_prev = 0;
  1450.   vid_stream->mblock.recon_down_back_prev = 0;
  1451.  
  1452.   /* Reset macroblock address. */
  1453.  
  1454.   vid_stream->mblock.mb_address = ((vid_stream->slice.vert_pos - 1) *
  1455.                    vid_stream->mb_width) - 1;
  1456.  
  1457.   /* Reset past dct dc y, cr, and cb values. */
  1458.  
  1459.   vid_stream->block.dct_dc_y_past = 1024;
  1460.   vid_stream->block.dct_dc_cr_past = 1024;
  1461.   vid_stream->block.dct_dc_cb_past = 1024;
  1462.  
  1463.   return PARSE_OK;
  1464. }
  1465.  
  1466.  
  1467.  
  1468. /*
  1469.  *--------------------------------------------------------------
  1470.  *
  1471.  * ParseMacroBlock --
  1472.  *
  1473.  *      Parseoff macroblock. Reconstructs DCT values. Applies
  1474.  *      inverse DCT, reconstructs motion vectors, calculates and
  1475.  *      set pixel values for macroblock in current pict image
  1476.  *      structure.
  1477.  *
  1478.  * Results:
  1479.  *      Here's where everything really happens. Welcome to the
  1480.  *      heart of darkness.
  1481.  *
  1482.  * Side effects:
  1483.  *      Bit stream irreversibly parsed off.
  1484.  *
  1485.  *--------------------------------------------------------------
  1486.  */
  1487.  
  1488. static int
  1489. ParseMacroBlock(vid_stream)
  1490.   VidStream *vid_stream;
  1491. {
  1492.   int addr_incr;
  1493.   unsigned int data;
  1494.   int mask, i, recon_right_for, recon_down_for, recon_right_back,
  1495.       recon_down_back;
  1496.   int zero_block_flag;
  1497.   BOOLEAN mb_quant, mb_motion_forw, mb_motion_back, mb_pattern;
  1498.   int no_dith_flag = 0;
  1499.   static char mbtyp[20];
  1500.   int result;
  1501.   unsigned int mb_scratch; /* used in Decode macros */
  1502.  
  1503.   mbSizeCount = bitCountRead();
  1504.  
  1505.   /*
  1506.    * Parse off macroblock address increment and add to macroblock address.
  1507.    */
  1508.   do {
  1509.     unsigned int index;                       
  1510.     show_bits11(index);                       
  1511.     addr_incr = mb_addr_inc[index].value;    
  1512.     flush_bits(mb_addr_inc[index].num_bits);     
  1513.     if (mb_addr_inc[index].num_bits==0) {
  1514.       /* Error in table lookup! */
  1515.       fprintf(stderr,"Error in macroblock increment at frame %d, PREVIOUS mb %d\n",
  1516.           blks.frame, vid_stream->mblock.mb_address);
  1517.       fprintf(stderr,"\tat byte offset %d in file.  Ignoring.\n", bitCountRead());
  1518.       addr_incr = 0;
  1519.     }
  1520.     if (addr_incr == MB_ESCAPE) {
  1521.       vid_stream->mblock.mb_address += 33;
  1522.       addr_incr = MB_STUFFING;
  1523.     }
  1524.   } while (addr_incr == MB_STUFFING);
  1525.   vid_stream->mblock.mb_address += addr_incr;
  1526.  
  1527.   if (vid_stream->mblock.mb_address > (vid_stream->mb_height *
  1528.                        vid_stream->mb_width - 1)) {
  1529.     sprintf(errorSpecifics,"\nMB address is %d, height is %d, width %d.\n",
  1530.         vid_stream->mblock.mb_address,
  1531.         vid_stream->mb_height,vid_stream->mb_width);
  1532.     return SKIP_TO_START_CODE;
  1533.   }
  1534.  
  1535.   /*
  1536.    * If macroblocks have been skipped, process skipped macroblocks.
  1537.    */
  1538.  
  1539.   if (vid_stream->mblock.mb_address - vid_stream->mblock.past_mb_addr > 1) {
  1540.     blks.mb_skipped += vid_stream->mblock.mb_address - vid_stream->mblock.past_mb_addr-1;
  1541.     if (vid_stream->picture.code_type == P_TYPE)
  1542.       ProcessSkippedPFrameMBlocks(vid_stream);
  1543.     else if (vid_stream->picture.code_type == B_TYPE)
  1544.       ProcessSkippedBFrameMBlocks(vid_stream);
  1545.   } else blks.mb_coded++;
  1546.   mbSizeCount = bitCountRead();
  1547.   /* Set past macroblock address to current macroblock address. */
  1548.   vid_stream->mblock.past_mb_addr = vid_stream->mblock.mb_address;
  1549.  
  1550.   /* Based on picture type decode macroblock type. */
  1551.   switch (vid_stream->picture.code_type) {
  1552.   case I_TYPE:
  1553.     DecodeMBTypeI(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
  1554.           vid_stream->mblock.mb_intra);
  1555.     break;
  1556.  
  1557.   case P_TYPE:
  1558.     DecodeMBTypeP(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
  1559.           vid_stream->mblock.mb_intra);
  1560.     break;
  1561.  
  1562.   case B_TYPE:
  1563.     DecodeMBTypeB(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
  1564.           vid_stream->mblock.mb_intra);
  1565.     break;
  1566.   }
  1567.  
  1568.   /* If quantization flag set, parse off new quantization scale. */
  1569.  
  1570.   if (mb_quant == TRUE) {
  1571.     get_bits5(data);
  1572.     vid_stream->slice.quant_scale = data;
  1573.   }
  1574.   stat_a[vid_stream->picture.code_type].qual += vid_stream->slice.quant_scale;
  1575.   stat_a[vid_stream->picture.code_type].qnum++;
  1576.   if (opts&COLLECTING&BLOCK_INFO) {
  1577.     blks.qs=vid_stream->slice.quant_scale;
  1578.     blks.block++;
  1579.     /* Clear, so we dont get old data later */
  1580.     *dctSpecifics='\0';
  1581.   }
  1582.   if (opts&COLLECTING&QSCALE_INFO) {
  1583.     blks.q[vid_stream->picture.code_type][vid_stream->slice.quant_scale]++;
  1584.   }
  1585.   
  1586.   /* If forward motion vectors exist... */
  1587.   if (mb_motion_forw == TRUE) {
  1588.  
  1589.     /* Parse off and decode horizontal forward motion vector. */
  1590.     DecodeMotionVectors(vid_stream->mblock.motion_h_forw_code);
  1591.  
  1592.     /* If horiz. forward r data exists, parse off. */
  1593.  
  1594.     if ((vid_stream->picture.forw_f != 1) &&
  1595.     (vid_stream->mblock.motion_h_forw_code != 0)) {
  1596.       get_bitsn(vid_stream->picture.forw_r_size, data);
  1597.       vid_stream->mblock.motion_h_forw_r = data;
  1598.     }
  1599.     /* Parse off and decode vertical forward motion vector. */
  1600.     DecodeMotionVectors(vid_stream->mblock.motion_v_forw_code);
  1601.  
  1602.     /* If vert. forw. r data exists, parse off. */
  1603.  
  1604.     if ((vid_stream->picture.forw_f != 1) &&
  1605.     (vid_stream->mblock.motion_v_forw_code != 0)) {
  1606.       get_bitsn(vid_stream->picture.forw_r_size, data);
  1607.       vid_stream->mblock.motion_v_forw_r = data;
  1608.     }
  1609.   }
  1610.   /* If back motion vectors exist... */
  1611.   if (mb_motion_back == TRUE) {
  1612.  
  1613.     /* Parse off and decode horiz. back motion vector. */
  1614.     DecodeMotionVectors(vid_stream->mblock.motion_h_back_code);
  1615.  
  1616.     /* If horiz. back r data exists, parse off. */
  1617.  
  1618.     if ((vid_stream->picture.back_f != 1) &&
  1619.     (vid_stream->mblock.motion_h_back_code != 0)) {
  1620.       get_bitsn(vid_stream->picture.back_r_size, data);
  1621.       vid_stream->mblock.motion_h_back_r = data;
  1622.     }
  1623.     /* Parse off and decode vert. back motion vector. */
  1624.     DecodeMotionVectors(vid_stream->mblock.motion_v_back_code);
  1625.  
  1626.     /* If vert. back r data exists, parse off. */
  1627.  
  1628.     if ((vid_stream->picture.back_f != 1) &&
  1629.     (vid_stream->mblock.motion_v_back_code != 0)) {
  1630.       get_bitsn(vid_stream->picture.back_r_size, data);
  1631.       vid_stream->mblock.motion_v_back_r = data;
  1632.     }
  1633.   }
  1634.   if (COLLECTING) {
  1635.     if (vid_stream->mblock.mb_intra) {
  1636.       stat_a[0].i_mbnum++;
  1637.       mbCBPPtr = stat_a[0].i_mbcbp;
  1638.       mbCoeffPtr = stat_a[0].i_mbcoeff;
  1639.       mbSizePtr = &(stat_a[0].i_mbsize);
  1640.     } else if (mb_motion_back && mb_motion_forw) {
  1641.       stat_a[0].bi_mbnum++;
  1642.       mbCBPPtr = stat_a[0].bi_mbcbp;
  1643.       mbCoeffPtr = stat_a[0].bi_mbcoeff;
  1644.       mbSizePtr = &(stat_a[0].bi_mbsize);
  1645.     } else if (mb_motion_back) {
  1646.       stat_a[0].b_mbnum++;
  1647.       mbCBPPtr = stat_a[0].b_mbcbp;
  1648.       mbCoeffPtr = stat_a[0].b_mbcoeff;
  1649.       mbSizePtr = &(stat_a[0].b_mbsize);
  1650.     } else {
  1651.       stat_a[0].p_mbnum++;
  1652.       mbCBPPtr = stat_a[0].p_mbcbp;
  1653.       mbCoeffPtr = stat_a[0].p_mbcoeff;
  1654.       mbSizePtr = &(stat_a[0].p_mbsize);
  1655.     }
  1656.   }
  1657.  
  1658.   /* If mblock pattern flag set, parse and decode CBP (code block pattern). */
  1659.   if (mb_pattern == TRUE) {
  1660.     DecodeCBP(vid_stream->mblock.cbp);
  1661.   }
  1662.   /* Otherwise, set CBP to zero. */
  1663.   else
  1664.     vid_stream->mblock.cbp = 0;
  1665.  
  1666.  
  1667.   if (COLLECTING) mbCBPPtr[vid_stream->mblock.cbp]++;
  1668.  
  1669.   /* Reconstruct motion vectors depending on picture type. */
  1670.   if (vid_stream->picture.code_type == P_TYPE) {
  1671.  
  1672.     /*
  1673.      * If no forw motion vectors, reset previous and current vectors to 0.
  1674.      */
  1675.  
  1676.     if (!mb_motion_forw) {
  1677.       recon_right_for = 0;
  1678.       recon_down_for = 0;
  1679.       vid_stream->mblock.recon_right_for_prev = 0;
  1680.       vid_stream->mblock.recon_down_for_prev = 0;
  1681.     }
  1682.     /*
  1683.      * Otherwise, compute new forw motion vectors. Reset previous vectors to
  1684.      * current vectors.
  1685.      */
  1686.  
  1687.     else {
  1688.       ComputeForwVector(&recon_right_for, &recon_down_for);
  1689.     }
  1690.   }
  1691.   if (vid_stream->picture.code_type == B_TYPE) {
  1692.  
  1693.     /* Reset prev. and current vectors to zero if mblock is intracoded. */
  1694.  
  1695.     if (vid_stream->mblock.mb_intra) {
  1696.       vid_stream->mblock.recon_right_for_prev = 0;
  1697.       vid_stream->mblock.recon_down_for_prev = 0;
  1698.       vid_stream->mblock.recon_right_back_prev = 0;
  1699.       vid_stream->mblock.recon_down_back_prev = 0;
  1700.     } else {
  1701.  
  1702.       /* If no forw vectors, current vectors equal prev. vectors. */
  1703.  
  1704.       if (!mb_motion_forw) {
  1705.     recon_right_for = vid_stream->mblock.recon_right_for_prev;
  1706.     recon_down_for = vid_stream->mblock.recon_down_for_prev;
  1707.       }
  1708.       /*
  1709.        * Otherwise compute forw. vectors. Reset prev vectors to new values.
  1710.        */
  1711.  
  1712.       else {
  1713.         ComputeForwVector(&recon_right_for, &recon_down_for);
  1714.       }
  1715.  
  1716.       /* If no back vectors, set back vectors to prev back vectors. */
  1717.  
  1718.       if (!mb_motion_back) {
  1719.     recon_right_back = vid_stream->mblock.recon_right_back_prev;
  1720.     recon_down_back = vid_stream->mblock.recon_down_back_prev;
  1721.       }
  1722.       /* Otherwise compute new vectors and reset prev. back vectors. */
  1723.  
  1724.       else {
  1725.     ComputeBackVector(&recon_right_back, &recon_down_back);
  1726.       }
  1727.  
  1728.       /*
  1729.        * Store vector existance flags in structure for possible skipped
  1730.        * macroblocks to follow.
  1731.        */
  1732.  
  1733.       vid_stream->mblock.bpict_past_forw = mb_motion_forw;
  1734.       vid_stream->mblock.bpict_past_back = mb_motion_back;
  1735.     }
  1736.   }
  1737.  
  1738.   if (COLLECTING&opts&BLOCK_INFO) {
  1739.     if (vid_stream->mblock.mb_intra) {
  1740.       sprintf(mbtyp,"intra");
  1741.     } else if (mb_motion_back && mb_motion_forw) {
  1742.       sprintf(mbtyp,"forw+back <%d, %d> <%d, %d>",
  1743.           recon_right_for, recon_down_for,
  1744.           recon_right_back, recon_down_back);
  1745.     } else if (mb_motion_back) {
  1746.       sprintf(mbtyp,"back <%d, %d>",recon_right_back, recon_down_back);
  1747.     } else if (mb_motion_forw) {
  1748.       sprintf(mbtyp,"forw <%d, %d>",recon_right_for, recon_down_for);
  1749.     } else 
  1750.  
  1751.       sprintf(mbtyp,"0 motion, %s",
  1752.           mb_quant ? "Quant and cbp" : "cbp");
  1753. #ifdef not_defined
  1754.     /* old code to print all flags, silly really */
  1755.     sprintf(mbtyp,"No motion? %1u%1u%1u%1u%1u (%x, %x, %x)",
  1756.         mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
  1757.         vid_stream->mblock.mb_intra,(mb_pattern?mb_scratch:0xffffffff),
  1758.         coded_block_pattern[mb_scratch].cbp,
  1759.         coded_block_pattern[mb_scratch].num_bits);
  1760. #endif
  1761.   }
  1762.  
  1763.   /* For each possible block in macroblock. */
  1764. {
  1765.    {
  1766.       for (mask = 32, i = 0; i < 6; mask >>= 1, i++) {
  1767.  
  1768.     /* If block exists... */
  1769.     if (vid_stream->mblock.mb_intra) {
  1770.       zero_block_flag = 0;
  1771.       if ((opts&VERIFY) || (opts&COLLECTING&HIST_INFO) ||
  1772.           (opts&COLLECTING&DCT_INFO)) {
  1773.         if ((result=ParseReconBlock(i))!=PARSE_OK) 
  1774.           return result;
  1775.       } else ParseAwayBlock(i);
  1776.     } else {
  1777.       if (vid_stream->mblock.cbp & mask) {
  1778.         blks.cblks++;
  1779.         blks.chist[i]++;
  1780.         zero_block_flag = 0;
  1781.         if ((opts&VERIFY) || (opts&COLLECTING&HIST_INFO) ||
  1782.         (opts&COLLECTING&DCT_INFO)) {
  1783.           if ((result=ParseReconBlock(i))!=PARSE_OK) 
  1784.         return result;
  1785.         } else ParseAwayBlock(i);
  1786.       } else {
  1787.         zero_block_flag = 1;        
  1788.       }
  1789.       blks.nblks++;
  1790.     }
  1791.     if (opts&VERIFY) { /* No need to do this if not verifying */
  1792.       if (vid_stream->mblock.mb_intra) {
  1793.         int result;
  1794.         if ((result=ReconIMBlock(vid_stream, i)) != PARSE_OK) 
  1795.           return result;
  1796.       } else if (mb_motion_forw && mb_motion_back) {
  1797.         ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1798.               recon_right_back, recon_down_back, zero_block_flag);
  1799.       } else if (mb_motion_forw || (vid_stream->picture.code_type == P_TYPE)) {
  1800.         ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1801.              zero_block_flag);
  1802.       } else if (mb_motion_back) {
  1803.         ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back,
  1804.              zero_block_flag);
  1805.       }
  1806.     }
  1807.       }
  1808.     }
  1809.   }
  1810.  
  1811.   if ((ditherType == MBORDERED_DITHER) && (!no_dith_flag)) {
  1812.     if ((vid_stream->picture.code_type == 2) &&
  1813.     (vid_stream->mblock.cbp == 0) &&
  1814.     (!vid_stream->mblock.mb_intra)) {
  1815.  
  1816.       ditherFlags[vid_stream->mblock.mb_address] = 0;
  1817.     }
  1818.     else {
  1819.       ditherFlags[vid_stream->mblock.mb_address] = 1;
  1820.     }
  1821.   }
  1822.  
  1823.  
  1824.   /* If D Type picture, flush marker bit. */
  1825.   if (vid_stream->picture.code_type == 4)
  1826.     flush_bits(1);
  1827.  
  1828.   /* If macroblock was intracoded, set macroblock past intra address. */
  1829.   if (vid_stream->mblock.mb_intra)
  1830.     vid_stream->mblock.past_intra_addr =
  1831.       vid_stream->mblock.mb_address;
  1832.  
  1833.   if (opts&COLLECTING&BLOCK_INFO) {
  1834.     if ((vid_stream->mblock.mb_intra) || (!mb_pattern))
  1835.       fprintf(block_fp,"block %d %c %d %d %s%s\n",
  1836.           blks.block-1,"0IPBD"[vid_stream->picture.code_type],
  1837.           blks.qs, bitCountRead() - mbSizeCount, mbtyp,
  1838.           dctSpecifics /* null if not collecting them */
  1839.           );
  1840.     else  {
  1841.     fprintf(block_fp,"block %d %c %d %d %s %1u%1u%1u%1u%1u%1u%s\n",
  1842.         blks.block-1,
  1843.         "0IPBD"[vid_stream->picture.code_type],
  1844.         blks.qs, bitCountRead() - mbSizeCount, mbtyp,
  1845.         (vid_stream->mblock.cbp&0x20)>>5,
  1846.         (vid_stream->mblock.cbp&0x10)>>4,
  1847.         (vid_stream->mblock.cbp&0x08)>>3,
  1848.         (vid_stream->mblock.cbp&0x04)>>2,
  1849.         (vid_stream->mblock.cbp&0x02)>>1,
  1850.         vid_stream->mblock.cbp&0x01,
  1851.         dctSpecifics /* null if not collecting them */
  1852.         );
  1853.       }
  1854.   }
  1855.   if (COLLECTING) *mbSizePtr += bitCountRead() - mbSizeCount;
  1856.   return PARSE_OK;
  1857. }
  1858.  
  1859.  
  1860.  
  1861. /*
  1862.  *--------------------------------------------------------------
  1863.  *
  1864.  * ReconIMBlock --
  1865.  *
  1866.  *    Reconstructs intra coded macroblock.
  1867.  *
  1868.  * Results:
  1869.  *    None.
  1870.  *
  1871.  * Side effects:
  1872.  *    None.
  1873.  *
  1874.  *--------------------------------------------------------------
  1875.  */
  1876.  
  1877. #define video_assert(x,expression)\
  1878.   if (!(expression)) {\
  1879.   sprintf (errorSpecifics,"\nBad crop value (%d) at line %d\n", x, __LINE__);\
  1880.   return SKIP_TO_START_CODE;}
  1881. #define assertCrop(x)    video_assert(x,((x) >= -MAX_NEG_CROP) && \
  1882.                  ((x) <= 2048+MAX_NEG_CROP))
  1883.  
  1884. static int
  1885. ReconIMBlock(vid_stream, bnum)
  1886.   VidStream *vid_stream;
  1887.   int bnum;
  1888. {
  1889.   int mb_row, mb_col, row, col, row_size, rr;
  1890.   unsigned char *dest;
  1891.  
  1892.   /* Calculate macroblock row and column from address. */
  1893.  
  1894.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  1895.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  1896.  
  1897.  
  1898.   /* If block is luminance block... */
  1899.  
  1900.   if (bnum < 4) {
  1901.  
  1902.     /* Calculate row and col values for upper left pixel of block. */
  1903.  
  1904.     row = mb_row * 16;
  1905.     col = mb_col * 16;
  1906.     if (bnum > 1)
  1907.       row += 8;
  1908.     if (bnum % 2)
  1909.       col += 8;
  1910.  
  1911.     /* Set dest to luminance plane of current pict image. */
  1912.  
  1913.     dest = vid_stream->current->luminance;
  1914.  
  1915.     /* Establish row size. */
  1916.  
  1917.     row_size = vid_stream->mb_width * 16;
  1918.   }
  1919.   /* Otherwise if block is Cb block... */
  1920.  
  1921.   else if (bnum == 4) {
  1922.  
  1923.     /* Set dest to Cb plane of current pict image. */
  1924.  
  1925.     dest = vid_stream->current->Cb;
  1926.  
  1927.     /* Establish row size. */
  1928.  
  1929.     row_size = vid_stream->mb_width * 8;
  1930.  
  1931.     /* Calculate row,col for upper left pixel of block. */
  1932.  
  1933.     row = mb_row * 8;
  1934.     col = mb_col * 8;
  1935.   }
  1936.   /* Otherwise block is Cr block, and ... */
  1937.  
  1938.   else {
  1939.  
  1940.     /* Set dest to Cr plane of current pict image. */
  1941.  
  1942.     dest = vid_stream->current->Cr;
  1943.  
  1944.     /* Establish row size. */
  1945.  
  1946.     row_size = vid_stream->mb_width * 8;
  1947.  
  1948.     /* Calculate row,col for upper left pixel value of block. */
  1949.  
  1950.     row = mb_row * 8;
  1951.     col = mb_col * 8;
  1952.   }
  1953.  
  1954.   /*
  1955.    * For each pixel in block, set to cropped reconstructed value from inverse
  1956.    * dct.
  1957.    */
  1958.   {
  1959.     short *sp = &vid_stream->block.dct_recon[0][0];
  1960.     unsigned char *cm = cropTbl + MAX_NEG_CROP;
  1961.     dest += row * row_size + col;
  1962.     for (rr = 0; rr < 4; rr++, sp += 16, dest += row_size) {
  1963.       dest[0] = cm[sp[0]];
  1964.       assertCrop(sp[0]);
  1965.       dest[1] = cm[sp[1]];
  1966.       assertCrop(sp[1]);
  1967.       dest[2] = cm[sp[2]];
  1968.       assertCrop(sp[2]);
  1969.       dest[3] = cm[sp[3]];
  1970.       assertCrop(sp[3]);
  1971.       dest[4] = cm[sp[4]];
  1972.       assertCrop(sp[4]);
  1973.       dest[5] = cm[sp[5]];
  1974.       assertCrop(sp[5]);
  1975.       dest[6] = cm[sp[6]];
  1976.       assertCrop(sp[6]);
  1977.       dest[7] = cm[sp[7]];
  1978.       assertCrop(sp[7]);
  1979.  
  1980.       dest += row_size;
  1981.       dest[0] = cm[sp[8]];
  1982.       assertCrop(sp[8]);
  1983.       dest[1] = cm[sp[9]];
  1984.       assertCrop(sp[9]);
  1985.       dest[2] = cm[sp[10]];
  1986.       assertCrop(sp[10]);
  1987.       dest[3] = cm[sp[11]];
  1988.       assertCrop(sp[11]);
  1989.       dest[4] = cm[sp[12]];
  1990.       assertCrop(sp[12]);
  1991.       dest[5] = cm[sp[13]];
  1992.       assertCrop(sp[13]);
  1993.       dest[6] = cm[sp[14]];
  1994.       assertCrop(sp[14]);
  1995.       dest[7] = cm[sp[15]];
  1996.       assertCrop(sp[15]);
  1997.     }
  1998.   }
  1999.   return PARSE_OK;
  2000. }
  2001.  
  2002.  
  2003.  
  2004. /*
  2005.  *--------------------------------------------------------------
  2006.  *
  2007.  * ReconPMBlock --
  2008.  *
  2009.  *    Reconstructs forward predicted macroblocks.
  2010.  *
  2011.  * Results:
  2012.  *      None.
  2013.  *
  2014.  * Side effects:
  2015.  *      None.
  2016.  *
  2017.  *--------------------------------------------------------------
  2018.  */
  2019.  
  2020. static void
  2021. ReconPMBlock(vid_stream, bnum, recon_right_for, recon_down_for, zflag)
  2022.   VidStream *vid_stream;
  2023.   int bnum, recon_right_for, recon_down_for, zflag;
  2024. {
  2025.   int mb_row, mb_col, row, col, row_size, rr;
  2026.   unsigned char *dest, *past;
  2027.   static int right_for, down_for, right_half_for, down_half_for;
  2028.   unsigned char *rindex1, *rindex2;
  2029.   unsigned char *index;
  2030.   short int *blockvals;
  2031.   int maxx, maxy, cc;
  2032.   int illegalBlock = 0;
  2033.   int row_start, row_end, rfirst, rlast, col_start, col_end, cfirst, clast;
  2034.  
  2035.   /* Calculate macroblock row and column from address. */
  2036.  
  2037.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  2038.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  2039.  
  2040.   if (bnum < 4) {
  2041.  
  2042.     /* Calculate right_for, down_for motion vectors. */
  2043.  
  2044.     right_for = recon_right_for >> 1;
  2045.     down_for = recon_down_for >> 1;
  2046.     right_half_for = recon_right_for & 0x1;
  2047.     down_half_for = recon_down_for & 0x1;
  2048.  
  2049.     /* Set dest to luminance plane of current pict image. */
  2050.  
  2051.     dest = vid_stream->current->luminance;
  2052.  
  2053.     if (vid_stream->picture.code_type == B_TYPE) {
  2054.       if (vid_stream->past != NULL)
  2055.     past = vid_stream->past->luminance;
  2056.     } else {
  2057.  
  2058.       /* Set predicitive frame to current future frame. */
  2059.  
  2060.       if (vid_stream->future != NULL)
  2061.     past = vid_stream->future->luminance;
  2062.     }
  2063.  
  2064.     /* Establish row size. */
  2065.  
  2066.     row_size = vid_stream->mb_width << 4;
  2067.  
  2068.     /* Calculate row,col of upper left pixel in block. */
  2069.  
  2070.     row = mb_row << 4;
  2071.     col = mb_col << 4;
  2072.     if (bnum > 1)
  2073.       row += 8;
  2074.     if (bnum % 2)
  2075.       col += 8;
  2076.  
  2077.     /* Check for block illegality. */
  2078.  
  2079.     maxx = lmaxx; maxy = lmaxy;
  2080.  
  2081.     if (row + down_for > maxy) illegalBlock |= 0x4;
  2082.     else if (row + down_for < 0)  illegalBlock |= 0x1;
  2083.     
  2084.     if (col + right_for > maxx) illegalBlock |= 0x2;
  2085.     else if (col + right_for < 0) illegalBlock |= 0x8;
  2086.     if (illegalBlock) {
  2087.       fprintf(stderr,"Illegal vector in luminance forward-reconstruction of <%d, %d>\n\
  2088.                frame %d, macro block %d, block %d\n",
  2089.           row + down_for, col + right_for, blks.frame,
  2090.           vid_stream->mblock.mb_address, bnum);
  2091.     }
  2092.   }
  2093.   /* Otherwise, block is NOT luminance block, ... */
  2094.  
  2095.   else {
  2096.  
  2097.     /* Construct motion vectors. */
  2098.  
  2099.     recon_right_for /= 2;
  2100.     recon_down_for /= 2;
  2101.     right_for = recon_right_for >> 1;
  2102.     down_for = recon_down_for >> 1;
  2103.     right_half_for = recon_right_for & 0x1;
  2104.     down_half_for = recon_down_for & 0x1;
  2105.  
  2106.     /* Establish row size. */
  2107.  
  2108.     row_size = vid_stream->mb_width << 3;
  2109.  
  2110.     /* Calculate row,col of upper left pixel in block. */
  2111.  
  2112.     row = mb_row << 3;
  2113.     col = mb_col << 3;
  2114.  
  2115.     /* Check for block illegality. */
  2116.  
  2117.     maxx = cmaxx; maxy = cmaxy; 
  2118.  
  2119.     if (row + down_for > maxy) illegalBlock |= 0x4;
  2120.     else if (row + down_for < 0) illegalBlock |= 0x1;
  2121.  
  2122.     if (col + right_for > maxx) illegalBlock  |= 0x2;
  2123.     else if (col + right_for < 0) illegalBlock |= 0x8;
  2124.     if (illegalBlock) {
  2125.       fprintf(stderr,"Illegal vector in Cr/Cb forward-reconstruction of <%d, %d>\n\
  2126.                frame %d, macro block %d, block %d\n",
  2127.           row + down_for, col + right_for, blks.frame,
  2128.           vid_stream->mblock.mb_address, bnum);
  2129.     }
  2130.  
  2131.     /* If block is Cr block... */
  2132.  
  2133.     if (bnum == 4) {
  2134.  
  2135.       /* Set dest to Cr plane of current pict image. */
  2136.  
  2137.       dest = vid_stream->current->Cr;
  2138.  
  2139.       if (vid_stream->picture.code_type == B_TYPE) {
  2140.  
  2141.     if (vid_stream->past != NULL)
  2142.       past = vid_stream->past->Cr;
  2143.       } else {
  2144.     if (vid_stream->future != NULL)
  2145.       past = vid_stream->future->Cr;
  2146.       }
  2147.     }
  2148.     /* Otherwise, block is Cb block... */
  2149.  
  2150.     else {
  2151.  
  2152.       /* Set dest to Cb plane of current pict image. */
  2153.  
  2154.       dest = vid_stream->current->Cb;
  2155.  
  2156.       if (vid_stream->picture.code_type == B_TYPE) {
  2157.     if (vid_stream->past != NULL)
  2158.       past = vid_stream->past->Cb;
  2159.       } else {
  2160.     if (vid_stream->future != NULL)
  2161.       past = vid_stream->future->Cb;
  2162.       }
  2163.     }
  2164.   }
  2165.  
  2166.   /* For each pixel in block... */
  2167.  
  2168.  
  2169.     index = dest + (row * row_size) + col;
  2170.     rindex1 = past + (row + down_for) * row_size + col + right_for;
  2171.     
  2172.     blockvals = &(vid_stream->block.dct_recon[0][0]);
  2173.     
  2174.     /*
  2175.      * Calculate predictive pixel value based on motion vectors and copy to
  2176.      * dest plane.
  2177.      */
  2178.     
  2179.     if ((!down_half_for) && (!right_half_for)) {
  2180.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2181.       if (!zflag)
  2182.     for (rr = 0; rr < 4; rr++) {
  2183.       index[0] = cm[(int) rindex1[0] + (int) blockvals[0]];
  2184.       index[1] = cm[(int) rindex1[1] + (int) blockvals[1]];
  2185.       index[2] = cm[(int) rindex1[2] + (int) blockvals[2]];
  2186.       index[3] = cm[(int) rindex1[3] + (int) blockvals[3]];
  2187.       index[4] = cm[(int) rindex1[4] + (int) blockvals[4]];
  2188.       index[5] = cm[(int) rindex1[5] + (int) blockvals[5]];
  2189.       index[6] = cm[(int) rindex1[6] + (int) blockvals[6]];
  2190.       index[7] = cm[(int) rindex1[7] + (int) blockvals[7]];
  2191.       index += row_size;
  2192.       rindex1 += row_size;
  2193.       
  2194.       index[0] = cm[(int) rindex1[0] + (int) blockvals[8]];
  2195.       index[1] = cm[(int) rindex1[1] + (int) blockvals[9]];
  2196.       index[2] = cm[(int) rindex1[2] + (int) blockvals[10]];
  2197.       index[3] = cm[(int) rindex1[3] + (int) blockvals[11]];
  2198.       index[4] = cm[(int) rindex1[4] + (int) blockvals[12]];
  2199.       index[5] = cm[(int) rindex1[5] + (int) blockvals[13]];
  2200.       index[6] = cm[(int) rindex1[6] + (int) blockvals[14]];
  2201.       index[7] = cm[(int) rindex1[7] + (int) blockvals[15]];
  2202.       blockvals += 16;
  2203.       index += row_size;
  2204.       rindex1 += row_size;
  2205.     }
  2206.       else {
  2207.     if (right_for & 0x1) {
  2208.       /* No alignment, use bye copy */
  2209.       for (rr = 0; rr < 4; rr++) {
  2210.         index[0] = rindex1[0];
  2211.         index[1] = rindex1[1];
  2212.         index[2] = rindex1[2];
  2213.         index[3] = rindex1[3];
  2214.         index[4] = rindex1[4];
  2215.         index[5] = rindex1[5];
  2216.         index[6] = rindex1[6];
  2217.         index[7] = rindex1[7];
  2218.         index += row_size;
  2219.         rindex1 += row_size;
  2220.         
  2221.         index[0] = rindex1[0];
  2222.         index[1] = rindex1[1];
  2223.         index[2] = rindex1[2];
  2224.         index[3] = rindex1[3];
  2225.         index[4] = rindex1[4];
  2226.         index[5] = rindex1[5];
  2227.         index[6] = rindex1[6];
  2228.         index[7] = rindex1[7];
  2229.         index += row_size;
  2230.         rindex1 += row_size;
  2231.       }
  2232.     } else if (right_for & 0x2) {
  2233.       /* Half-word bit aligned, use 16 bit copy */
  2234.       short *src = (short *)rindex1;
  2235.       short *dest = (short *)index;
  2236.       row_size >>= 1;
  2237.       for (rr = 0; rr < 4; rr++) {
  2238.         dest[0] = src[0];
  2239.         dest[1] = src[1];
  2240.         dest[2] = src[2];
  2241.         dest[3] = src[3];
  2242.         dest += row_size;
  2243.         src += row_size;
  2244.         
  2245.         dest[0] = src[0];
  2246.         dest[1] = src[1];
  2247.         dest[2] = src[2];
  2248.         dest[3] = src[3];
  2249.         dest += row_size;
  2250.         src += row_size;
  2251.       }
  2252.     } else {
  2253.       /* Word aligned, use 32 bit copy */
  2254.       int *src = (int *)rindex1;
  2255.       int *dest = (int *)index;
  2256.       row_size >>= 2;
  2257.       for (rr = 0; rr < 4; rr++) {
  2258.         dest[0] = src[0];
  2259.         dest[1] = src[1];
  2260.         dest += row_size;
  2261.         src += row_size;
  2262.         
  2263.         dest[0] = src[0];
  2264.         dest[1] = src[1];
  2265.         dest += row_size;
  2266.         src += row_size;
  2267.       }
  2268.     }
  2269.       }
  2270.     } else {
  2271.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2272.       rindex2 = rindex1 + right_half_for + (down_half_for * row_size);
  2273.       if (!zflag)
  2274.     for (rr = 0; rr < 4; rr++) {
  2275.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[0]];
  2276.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[1]];
  2277.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[2]];
  2278.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[3]];
  2279.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[4]];
  2280.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[5]];
  2281.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[6]];
  2282.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[7]];
  2283.       index += row_size;
  2284.       rindex1 += row_size;
  2285.       rindex2 += row_size;
  2286.       
  2287.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[8]];
  2288.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[9]];
  2289.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[10]];
  2290.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[11]];
  2291.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[12]];
  2292.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[13]];
  2293.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[14]];
  2294.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[15]];
  2295.       blockvals += 16;
  2296.       index += row_size;
  2297.       rindex1 += row_size;
  2298.       rindex2 += row_size;
  2299.     }
  2300.       else
  2301.     for (rr = 0; rr < 4; rr++) {
  2302.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2303.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2304.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2305.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2306.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2307.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2308.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2309.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2310.       index += row_size;
  2311.       rindex1 += row_size;
  2312.       rindex2 += row_size;
  2313.       
  2314.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2315.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2316.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2317.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2318.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2319.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2320.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2321.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2322.       index += row_size;
  2323.       rindex1 += row_size;
  2324.       rindex2 += row_size;
  2325.     }
  2326.     }
  2327. }
  2328.  
  2329.  
  2330. /*
  2331.  *--------------------------------------------------------------
  2332.  *
  2333.  * ReconBMBlock --
  2334.  *
  2335.  *    Reconstructs back predicted macroblocks.
  2336.  *
  2337.  * Results:
  2338.  *      None.
  2339.  *
  2340.  * Side effects:
  2341.  *      None.
  2342.  *
  2343.  *--------------------------------------------------------------
  2344.  */
  2345.  
  2346. static void
  2347. ReconBMBlock(vid_stream, bnum, recon_right_back, recon_down_back, zflag)
  2348.   VidStream *vid_stream;
  2349.   int bnum, recon_right_back, recon_down_back, zflag;
  2350. {
  2351.   int mb_row, mb_col, row, col, row_size, rr;
  2352.   unsigned char *dest, *future;
  2353.   int right_back, down_back, right_half_back, down_half_back;
  2354.   unsigned char *rindex1, *rindex2;
  2355.   unsigned char *index;
  2356.   short int *blockvals;
  2357.  
  2358.   int illegalBlock = 0;
  2359.   int maxx, maxy, cc;
  2360.   int row_start, row_end, rlast, rfirst, col_start, col_end, clast, cfirst;
  2361.  
  2362.   /* Calculate macroblock row and column from address. */
  2363.  
  2364.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  2365.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  2366.  
  2367.   /* If block is luminance block... */
  2368.  
  2369.   if (bnum < 4) {
  2370.  
  2371.     /* Calculate right_back, down_bakc motion vectors. */
  2372.  
  2373.     right_back = recon_right_back >> 1;
  2374.     down_back = recon_down_back >> 1;
  2375.     right_half_back = recon_right_back & 0x1;
  2376.     down_half_back = recon_down_back & 0x1;
  2377.  
  2378.     /* Set dest to luminance plane of current pict image. */
  2379.  
  2380.     dest = vid_stream->current->luminance;
  2381.  
  2382.     /*
  2383.      * If future frame exists, set future to luminance plane of future frame.
  2384.      */
  2385.  
  2386.     if (vid_stream->future != NULL)
  2387.       future = vid_stream->future->luminance;
  2388.  
  2389.     /* Establish row size. */
  2390.  
  2391.     row_size = vid_stream->mb_width << 4;
  2392.  
  2393.     /* Calculate row,col of upper left pixel in block. */
  2394.  
  2395.     row = mb_row << 4;
  2396.     col = mb_col << 4;
  2397.     if (bnum > 1)
  2398.       row += 8;
  2399.     if (bnum % 2)
  2400.       col += 8;
  2401.  
  2402.     /* Check for block illegality. */
  2403.  
  2404.     maxx = lmaxx; maxy = lmaxy;
  2405.  
  2406.     if (row + down_back  > maxy) illegalBlock |= 0x4;
  2407.     else if (row + down_back < 0)  illegalBlock |= 0x1;
  2408.     
  2409.     if (col + right_back  > maxx) illegalBlock |= 0x2;
  2410.     else if (col + right_back < 0) illegalBlock |= 0x8;
  2411.     if (illegalBlock) {
  2412.       fprintf(stderr,"Illegal vector in luminance backward-reconstruction of <%d, %d>\n\
  2413.                frame %d, macro block %d, block %d\n",
  2414.           row + down_back, col + right_back, blks.frame,
  2415.           vid_stream->mblock.mb_address, bnum);
  2416.     }
  2417.  
  2418.   }
  2419.   /* Otherwise, block is NOT luminance block, ... */
  2420.  
  2421.   else {
  2422.  
  2423.     /* Construct motion vectors. */
  2424.  
  2425.     recon_right_back /= 2;
  2426.     recon_down_back /= 2;
  2427.     right_back = recon_right_back >> 1;
  2428.     down_back = recon_down_back >> 1;
  2429.     right_half_back = recon_right_back & 0x1;
  2430.     down_half_back = recon_down_back & 0x1;
  2431.  
  2432.     /* Establish row size. */
  2433.  
  2434.     row_size = vid_stream->mb_width << 3;
  2435.  
  2436.     /* Calculate row,col of upper left pixel in block. */
  2437.  
  2438.     row = mb_row << 3;
  2439.     col = mb_col << 3;
  2440.  
  2441.  
  2442.     /* Check for block illegality. */
  2443.  
  2444.     maxx = cmaxx; maxy = cmaxy;
  2445.  
  2446.     if (row + down_back  > maxy) illegalBlock |= 0x4;
  2447.     else if (row + down_back < 0) illegalBlock |= 0x1;
  2448.  
  2449.     if (col + right_back  > maxx) illegalBlock  |= 0x2;
  2450.     else if (col + right_back < 0) illegalBlock |= 0x8;
  2451.     if (illegalBlock) {
  2452.       fprintf(stderr,"Illegal vector in Cr/Cb backward-reconstruction of <%d, %d>\n\
  2453.                frame %d, macro block %d, block %d\n",
  2454.           row + down_back, col + right_back, blks.frame,
  2455.           vid_stream->mblock.mb_address, bnum);
  2456.     }
  2457.  
  2458.     /* If block is Cr block... */
  2459.  
  2460.     if (bnum == 4) {
  2461.  
  2462.       /* Set dest to Cr plane of current pict image. */
  2463.  
  2464.       dest = vid_stream->current->Cr;
  2465.  
  2466.       /*
  2467.        * If future frame exists, set future to Cr plane of future image.
  2468.        */
  2469.  
  2470.       if (vid_stream->future != NULL)
  2471.     future = vid_stream->future->Cr;
  2472.     }
  2473.     /* Otherwise, block is Cb block... */
  2474.  
  2475.     else {
  2476.  
  2477.       /* Set dest to Cb plane of current pict image. */
  2478.  
  2479.       dest = vid_stream->current->Cb;
  2480.  
  2481.       /*
  2482.        * If future frame exists, set future to Cb plane of future frame.
  2483.        */
  2484.  
  2485.       if (vid_stream->future != NULL)
  2486.     future = vid_stream->future->Cb;
  2487.     }
  2488.   }
  2489.  
  2490.   /* For each pixel in block do... */
  2491.  
  2492.     
  2493.     index = dest + (row * row_size) + col;
  2494.     rindex1 = future + (row + down_back) * row_size + col + right_back;
  2495.  
  2496.     blockvals = &(vid_stream->block.dct_recon[0][0]);
  2497.  
  2498.     if ((!right_half_back) && (!down_half_back)) {
  2499.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2500.       if (!zflag)
  2501.     for (rr = 0; rr < 4; rr++) {
  2502.       index[0] = cm[(int) rindex1[0] + (int) blockvals[0]];
  2503.       index[1] = cm[(int) rindex1[1] + (int) blockvals[1]];
  2504.       index[2] = cm[(int) rindex1[2] + (int) blockvals[2]];
  2505.       index[3] = cm[(int) rindex1[3] + (int) blockvals[3]];
  2506.       index[4] = cm[(int) rindex1[4] + (int) blockvals[4]];
  2507.       index[5] = cm[(int) rindex1[5] + (int) blockvals[5]];
  2508.       index[6] = cm[(int) rindex1[6] + (int) blockvals[6]];
  2509.       index[7] = cm[(int) rindex1[7] + (int) blockvals[7]];
  2510.       index += row_size;
  2511.       rindex1 += row_size;
  2512.       
  2513.       index[0] = cm[(int) rindex1[0] + (int) blockvals[8]];
  2514.       index[1] = cm[(int) rindex1[1] + (int) blockvals[9]];
  2515.       index[2] = cm[(int) rindex1[2] + (int) blockvals[10]];
  2516.       index[3] = cm[(int) rindex1[3] + (int) blockvals[11]];
  2517.       index[4] = cm[(int) rindex1[4] + (int) blockvals[12]];
  2518.       index[5] = cm[(int) rindex1[5] + (int) blockvals[13]];
  2519.       index[6] = cm[(int) rindex1[6] + (int) blockvals[14]];
  2520.       index[7] = cm[(int) rindex1[7] + (int) blockvals[15]];
  2521.       blockvals += 16;
  2522.       index += row_size;
  2523.       rindex1 += row_size;
  2524.     }
  2525.       else {
  2526.     if (right_back & 0x1) {
  2527.       /* No alignment, use bye copy */
  2528.       for (rr = 0; rr < 4; rr++) {
  2529.         index[0] = rindex1[0];
  2530.         index[1] = rindex1[1];
  2531.         index[2] = rindex1[2];
  2532.         index[3] = rindex1[3];
  2533.         index[4] = rindex1[4];
  2534.         index[5] = rindex1[5];
  2535.         index[6] = rindex1[6];
  2536.         index[7] = rindex1[7];
  2537.         index += row_size;
  2538.         rindex1 += row_size;
  2539.         
  2540.         index[0] = rindex1[0];
  2541.         index[1] = rindex1[1];
  2542.         index[2] = rindex1[2];
  2543.         index[3] = rindex1[3];
  2544.         index[4] = rindex1[4];
  2545.         index[5] = rindex1[5];
  2546.         index[6] = rindex1[6];
  2547.         index[7] = rindex1[7];
  2548.         index += row_size;
  2549.         rindex1 += row_size;
  2550.       }
  2551.     } else if (right_back & 0x2) {
  2552.       /* Half-word bit aligned, use 16 bit copy */
  2553.       short *src = (short *)rindex1;
  2554.       short *dest = (short *)index;
  2555.       row_size >>= 1;
  2556.       for (rr = 0; rr < 4; rr++) {
  2557.         dest[0] = src[0];
  2558.         dest[1] = src[1];
  2559.         dest[2] = src[2];
  2560.         dest[3] = src[3];
  2561.         dest += row_size;
  2562.         src += row_size;
  2563.         
  2564.         dest[0] = src[0];
  2565.         dest[1] = src[1];
  2566.         dest[2] = src[2];
  2567.         dest[3] = src[3];
  2568.         dest += row_size;
  2569.         src += row_size;
  2570.       }
  2571.     } else {
  2572.       /* Word aligned, use 32 bit copy */
  2573.       int *src = (int *)rindex1;
  2574.       int *dest = (int *)index;
  2575.       row_size >>= 2;
  2576.       for (rr = 0; rr < 4; rr++) {
  2577.         dest[0] = src[0];
  2578.         dest[1] = src[1];
  2579.         dest += row_size;
  2580.         src += row_size;
  2581.         
  2582.         dest[0] = src[0];
  2583.         dest[1] = src[1];
  2584.         dest += row_size;
  2585.         src += row_size;
  2586.       }
  2587.     }
  2588.       }
  2589.     } else {
  2590.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2591.       rindex2 = rindex1 + right_half_back + (down_half_back * row_size);
  2592.       if (!zflag)
  2593.     for (rr = 0; rr < 4; rr++) {
  2594.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[0]];
  2595.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[1]];
  2596.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[2]];
  2597.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[3]];
  2598.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[4]];
  2599.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[5]];
  2600.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[6]];
  2601.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[7]];
  2602.       index += row_size;
  2603.       rindex1 += row_size;
  2604.       rindex2 += row_size;
  2605.       
  2606.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[8]];
  2607.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[9]];
  2608.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[10]];
  2609.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[11]];
  2610.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[12]];
  2611.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[13]];
  2612.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[14]];
  2613.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[15]];
  2614.       blockvals += 16;
  2615.       index += row_size;
  2616.       rindex1 += row_size;
  2617.       rindex2 += row_size;
  2618.     }
  2619.       else
  2620.     for (rr = 0; rr < 4; rr++) {
  2621.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2622.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2623.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2624.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2625.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2626.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2627.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2628.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2629.       index += row_size;
  2630.       rindex1 += row_size;
  2631.       rindex2 += row_size;
  2632.       
  2633.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2634.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2635.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2636.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2637.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2638.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2639.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2640.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2641.       index += row_size;
  2642.       rindex1 += row_size;
  2643.       rindex2 += row_size;
  2644.     }
  2645.     }
  2646. }
  2647.  
  2648.  
  2649. /*
  2650.  *--------------------------------------------------------------
  2651.  *
  2652.  * ReconBiMBlock --
  2653.  *
  2654.  *    Reconstructs bidirectionally predicted macroblocks.
  2655.  *
  2656.  * Results:
  2657.  *      None.
  2658.  *
  2659.  * Side effects:
  2660.  *      None.
  2661.  *
  2662.  *--------------------------------------------------------------
  2663.  */
  2664.  
  2665. static void
  2666. ReconBiMBlock(vid_stream, bnum, recon_right_for, recon_down_for,
  2667.           recon_right_back, recon_down_back, zflag)
  2668.   VidStream *vid_stream;
  2669.   int bnum, recon_right_for, recon_down_for, recon_right_back, recon_down_back;
  2670.   int zflag;
  2671. {
  2672.   int mb_row, mb_col, row, col, row_size, rr;
  2673.   unsigned char *dest, *past, *future;
  2674.   int right_for, down_for, right_half_for, down_half_for;
  2675.   int right_back, down_back, right_half_back, down_half_back;
  2676.   unsigned char *index, *rindex1, *bindex1;
  2677.   short int *blockvals;
  2678.   int forw_row_start, back_row_start, forw_col_start, back_col_start;
  2679.  
  2680.   /* Calculate macroblock row and column from address. */
  2681.  
  2682.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  2683.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  2684.  
  2685.   /* If block is luminance block... */
  2686.  
  2687.   if (bnum < 4) {
  2688.  
  2689.     /*
  2690.      * Calculate right_for, down_for, right_half_for, down_half_for,
  2691.      * right_back, down_bakc, right_half_back, and down_half_back, motion
  2692.      * vectors.
  2693.      */
  2694.  
  2695.     right_for = recon_right_for >> 1;
  2696.     down_for = recon_down_for >> 1;
  2697.     right_half_for = recon_right_for & 0x1;
  2698.     down_half_for = recon_down_for & 0x1;
  2699.  
  2700.     right_back = recon_right_back >> 1;
  2701.     down_back = recon_down_back >> 1;
  2702.     right_half_back = recon_right_back & 0x1;
  2703.     down_half_back = recon_down_back & 0x1;
  2704.  
  2705.     /* Set dest to luminance plane of current pict image. */
  2706.  
  2707.     dest = vid_stream->current->luminance;
  2708.  
  2709.     /* If past frame exists, set past to luminance plane of past frame. */
  2710.  
  2711.     if (vid_stream->past != NULL)
  2712.       past = vid_stream->past->luminance;
  2713.  
  2714.     /*
  2715.      * If future frame exists, set future to luminance plane of future frame.
  2716.      */
  2717.  
  2718.     if (vid_stream->future != NULL)
  2719.       future = vid_stream->future->luminance;
  2720.  
  2721.     /* Establish row size. */
  2722.  
  2723.     row_size = (vid_stream->mb_width << 4);
  2724.  
  2725.     /* Calculate row,col of upper left pixel in block. */
  2726.  
  2727.     row = (mb_row << 4);
  2728.     col = (mb_col << 4);
  2729.     if (bnum > 1)
  2730.       row += 8;
  2731.     if (bnum & 0x01)
  2732.       col += 8;
  2733.  
  2734.     forw_col_start = col + right_for;
  2735.     forw_row_start = row + down_for;
  2736.  
  2737.     back_col_start = col + right_back;
  2738.     back_row_start = row + down_back;
  2739.  
  2740.     /* Check for illegal pred. blocks. */
  2741.     
  2742.     if ((forw_col_start > lmaxx) || (forw_col_start < 0) ||
  2743.     (forw_row_start > lmaxy) || (forw_row_start < 0))
  2744.       fprintf(stderr,"Illegal luminance forward vector in Bi-reconstruction <%d, %d>\n\
  2745.               in frame %d, macro block %d, block %d\n",
  2746.           forw_col_start, forw_row_start,blks.frame,
  2747.           vid_stream->mblock.mb_address, bnum);
  2748.     
  2749.     if ((back_col_start > lmaxx) || (back_col_start < 0) ||
  2750.         (back_row_start > lmaxy) || (back_row_start < 0)) 
  2751.       fprintf(stderr,"Illegal luminance backward vector in Bi-reconstruction <%d, %d>\n\
  2752.               in frame %d, macro block %d, block %d\n",
  2753.           forw_col_start, forw_row_start,blks.frame,
  2754.           vid_stream->mblock.mb_address, bnum);
  2755.  
  2756.   /* Otherwise, block is NOT luminance block, ... */
  2757.  
  2758.   } else {
  2759.  
  2760.     /* Construct motion vectors. */
  2761.  
  2762.     recon_right_for /= 2;
  2763.     recon_down_for /= 2;
  2764.     right_for = recon_right_for >> 1;
  2765.     down_for = recon_down_for >> 1;
  2766.     right_half_for = recon_right_for & 0x1;
  2767.     down_half_for = recon_down_for & 0x1;
  2768.  
  2769.     recon_right_back /= 2;
  2770.     recon_down_back /= 2;
  2771.     right_back = recon_right_back >> 1;
  2772.     down_back = recon_down_back >> 1;
  2773.     right_half_back = recon_right_back & 0x1;
  2774.     down_half_back = recon_down_back & 0x1;
  2775.  
  2776.     /* Establish row size. */
  2777.  
  2778.     row_size = (vid_stream->mb_width << 3);
  2779.  
  2780.     /* Calculate row,col of upper left pixel in block. */
  2781.  
  2782.     row = (mb_row << 3);
  2783.     col = (mb_col << 3);
  2784.  
  2785.     forw_col_start = col + right_for;
  2786.     forw_row_start = row + down_for;
  2787.  
  2788.     back_col_start = col + right_back;
  2789.     back_row_start = row + down_back;
  2790.  
  2791.  
  2792.     /* Check for illegal pred. blocks. */
  2793.  
  2794.     if ((forw_col_start > cmaxx) || (forw_col_start < 0) ||
  2795.     (forw_row_start > cmaxy) || (forw_row_start < 0))
  2796.       fprintf(stderr,"Illegal Cr/Cb forward vector in Bi-reconstruction <%d, %d>\n\
  2797.               in frame %d, macro block %d, block %d\n",
  2798.           forw_col_start, forw_row_start,blks.frame,
  2799.           vid_stream->mblock.mb_address, bnum);
  2800.  
  2801.     if ((back_col_start > cmaxx) || (back_col_start < 0) ||
  2802.         (back_row_start > cmaxy) || (back_row_start < 0)) 
  2803.       fprintf(stderr,"Illegal Cr/Cb backward vector in Bi-reconstruction <%d, %d>\n\
  2804.               in frame %d, macro block %d, block %d\n",
  2805.           forw_col_start, forw_row_start,blks.frame,
  2806.           vid_stream->mblock.mb_address, bnum);
  2807.  
  2808.  
  2809.     
  2810.     /* If block is Cr block... */
  2811.  
  2812.     if (bnum == 4) {
  2813.  
  2814.       /* Set dest to Cr plane of current pict image. */
  2815.  
  2816.       dest = vid_stream->current->Cr;
  2817.  
  2818.       /* If past frame exists, set past to Cr plane of past image. */
  2819.  
  2820.       if (vid_stream->past != NULL)
  2821.     past = vid_stream->past->Cr;
  2822.  
  2823.       /*
  2824.        * If future frame exists, set future to Cr plane of future image.
  2825.        */
  2826.  
  2827.       if (vid_stream->future != NULL)
  2828.     future = vid_stream->future->Cr;
  2829.     }
  2830.     /* Otherwise, block is Cb block... */
  2831.  
  2832.     else {
  2833.  
  2834.       /* Set dest to Cb plane of current pict image. */
  2835.  
  2836.       dest = vid_stream->current->Cb;
  2837.  
  2838.       /* If past frame exists, set past to Cb plane of past frame. */
  2839.  
  2840.       if (vid_stream->past != NULL)
  2841.     past = vid_stream->past->Cb;
  2842.  
  2843.       /*
  2844.        * If future frame exists, set future to Cb plane of future frame.
  2845.        */
  2846.  
  2847.       if (vid_stream->future != NULL)
  2848.     future = vid_stream->future->Cb;
  2849.     }
  2850.   }
  2851.  
  2852.   /* For each pixel in block... */
  2853.  
  2854.   index = dest + (row * row_size) + col;
  2855.  
  2856.   rindex1 = past + forw_row_start  * row_size + forw_col_start;
  2857.  
  2858.   bindex1 = future + back_row_start * row_size + back_col_start;
  2859.  
  2860.   blockvals = (short int *) &(vid_stream->block.dct_recon[0][0]);
  2861.  
  2862.   {
  2863.   unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2864.   if (!zflag)
  2865.     for (rr = 0; rr < 4; rr++) {
  2866.       index[0] = cm[((int) (rindex1[0] + bindex1[0]) >> 1) + blockvals[0]];
  2867.       index[1] = cm[((int) (rindex1[1] + bindex1[1]) >> 1) + blockvals[1]];
  2868.       index[2] = cm[((int) (rindex1[2] + bindex1[2]) >> 1) + blockvals[2]];
  2869.       index[3] = cm[((int) (rindex1[3] + bindex1[3]) >> 1) + blockvals[3]];
  2870.       index[4] = cm[((int) (rindex1[4] + bindex1[4]) >> 1) + blockvals[4]];
  2871.       index[5] = cm[((int) (rindex1[5] + bindex1[5]) >> 1) + blockvals[5]];
  2872.       index[6] = cm[((int) (rindex1[6] + bindex1[6]) >> 1) + blockvals[6]];
  2873.       index[7] = cm[((int) (rindex1[7] + bindex1[7]) >> 1) + blockvals[7]];
  2874.       index += row_size;
  2875.       rindex1 += row_size;
  2876.       bindex1 += row_size;
  2877.  
  2878.       index[0] = cm[((int) (rindex1[0] + bindex1[0]) >> 1) + blockvals[8]];
  2879.       index[1] = cm[((int) (rindex1[1] + bindex1[1]) >> 1) + blockvals[9]];
  2880.       index[2] = cm[((int) (rindex1[2] + bindex1[2]) >> 1) + blockvals[10]];
  2881.       index[3] = cm[((int) (rindex1[3] + bindex1[3]) >> 1) + blockvals[11]];
  2882.       index[4] = cm[((int) (rindex1[4] + bindex1[4]) >> 1) + blockvals[12]];
  2883.       index[5] = cm[((int) (rindex1[5] + bindex1[5]) >> 1) + blockvals[13]];
  2884.       index[6] = cm[((int) (rindex1[6] + bindex1[6]) >> 1) + blockvals[14]];
  2885.       index[7] = cm[((int) (rindex1[7] + bindex1[7]) >> 1) + blockvals[15]];
  2886.       blockvals += 16;
  2887.       index += row_size;
  2888.       rindex1 += row_size;
  2889.       bindex1 += row_size;
  2890.     }
  2891.  
  2892.   else
  2893.     for (rr = 0; rr < 4; rr++) {
  2894.       index[0] = (int) (rindex1[0] + bindex1[0]) >> 1;
  2895.       index[1] = (int) (rindex1[1] + bindex1[1]) >> 1;
  2896.       index[2] = (int) (rindex1[2] + bindex1[2]) >> 1;
  2897.       index[3] = (int) (rindex1[3] + bindex1[3]) >> 1;
  2898.       index[4] = (int) (rindex1[4] + bindex1[4]) >> 1;
  2899.       index[5] = (int) (rindex1[5] + bindex1[5]) >> 1;
  2900.       index[6] = (int) (rindex1[6] + bindex1[6]) >> 1;
  2901.       index[7] = (int) (rindex1[7] + bindex1[7]) >> 1;
  2902.       index += row_size;
  2903.       rindex1 += row_size;
  2904.       bindex1 += row_size;
  2905.  
  2906.       index[0] = (int) (rindex1[0] + bindex1[0]) >> 1;
  2907.       index[1] = (int) (rindex1[1] + bindex1[1]) >> 1;
  2908.       index[2] = (int) (rindex1[2] + bindex1[2]) >> 1;
  2909.       index[3] = (int) (rindex1[3] + bindex1[3]) >> 1;
  2910.       index[4] = (int) (rindex1[4] + bindex1[4]) >> 1;
  2911.       index[5] = (int) (rindex1[5] + bindex1[5]) >> 1;
  2912.       index[6] = (int) (rindex1[6] + bindex1[6]) >> 1;
  2913.       index[7] = (int) (rindex1[7] + bindex1[7]) >> 1;
  2914.       index += row_size;
  2915.       rindex1 += row_size;
  2916.       bindex1 += row_size;
  2917.     }
  2918.   }
  2919. }
  2920.  
  2921. /*
  2922.  *--------------------------------------------------------------
  2923.  *
  2924.  * ProcessSkippedPFrameMBlocks --
  2925.  *
  2926.  *    Processes skipped macroblocks in P frames.
  2927.  *
  2928.  * Results:
  2929.  *    Calculates pixel values for luminance, Cr, and Cb planes
  2930.  *      in current pict image for skipped macroblocks.
  2931.  *
  2932.  * Side effects:
  2933.  *    Pixel values in pict image changed.
  2934.  *
  2935.  *--------------------------------------------------------------
  2936.  */
  2937.  
  2938. static void
  2939. ProcessSkippedPFrameMBlocks(vid_stream)
  2940.   VidStream *vid_stream;
  2941. {
  2942.   int row_size, half_row, mb_row, mb_col, row, col, rr;
  2943.   int addr, row_incr, half_row_incr, crow, ccol;
  2944.   int *dest, *src, *dest1, *src1;
  2945.  
  2946.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  2947.  
  2948.   row_size = vid_stream->mb_width << 4;
  2949.   half_row = (row_size >> 1);
  2950.   row_incr = row_size >> 2;
  2951.   half_row_incr = half_row >> 2;
  2952.  
  2953.   /* For each skipped macroblock, do... */
  2954.  
  2955.   for (addr = vid_stream->mblock.past_mb_addr + 1;
  2956.        addr < vid_stream->mblock.mb_address; addr++) {
  2957.  
  2958.     if (opts&COLLECTING&BLOCK_INFO) {
  2959.       blks.block++;
  2960.       fprintf(block_fp,"block %d %c %d 0 skip\n",
  2961.           blks.block-1,"0IPBD"[vid_stream->picture.code_type],
  2962.           blks.qs);
  2963.     }
  2964.  
  2965.     /* Calculate macroblock row and col. */
  2966.     mb_row = addr / vid_stream->mb_width;
  2967.     mb_col = addr % vid_stream->mb_width;
  2968.  
  2969.     /* Calculate upper left pixel row,col for luminance plane. */
  2970.  
  2971.     row = mb_row << 4;
  2972.     col = mb_col << 4;
  2973.  
  2974.  
  2975.     /* For each row in macroblock luminance plane... */
  2976.  
  2977.     dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
  2978.     src = (int *)(vid_stream->future->luminance + (row * row_size) + col);
  2979.  
  2980.     for (rr = 0; rr < 8; rr++) {
  2981.  
  2982.       /* Copy pixel values from last I or P picture. */
  2983.  
  2984.       dest[0] = src[0];
  2985.       dest[1] = src[1];
  2986.       dest[2] = src[2];
  2987.       dest[3] = src[3];
  2988.       dest += row_incr;
  2989.       src += row_incr;
  2990.  
  2991.       dest[0] = src[0];
  2992.       dest[1] = src[1];
  2993.       dest[2] = src[2];
  2994.       dest[3] = src[3];
  2995.       dest += row_incr;
  2996.       src += row_incr;
  2997.     }
  2998.  
  2999.     /*
  3000.      * Divide row,col to get upper left pixel of macroblock in Cr and Cb
  3001.      * planes.
  3002.      */
  3003.  
  3004.     crow = row >> 1;
  3005.     ccol = col >> 1;
  3006.  
  3007.     /* For each row in Cr, and Cb planes... */
  3008.  
  3009.     dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
  3010.     src = (int *)(vid_stream->future->Cr + (crow * half_row) + ccol);
  3011.     dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
  3012.     src1 = (int *)(vid_stream->future->Cb + (crow * half_row) + ccol);
  3013.  
  3014.     for (rr = 0; rr < 4; rr++) {
  3015.  
  3016.       /* Copy pixel values from last I or P picture. */
  3017.  
  3018.       dest[0] = src[0];
  3019.       dest[1] = src[1];
  3020.  
  3021.       dest1[0] = src1[0];
  3022.       dest1[1] = src1[1];
  3023.  
  3024.       dest += half_row_incr;
  3025.       src += half_row_incr;
  3026.       dest1 += half_row_incr;
  3027.       src1 += half_row_incr;
  3028.  
  3029.       dest[0] = src[0];
  3030.       dest[1] = src[1];
  3031.  
  3032.       dest1[0] = src1[0];
  3033.       dest1[1] = src1[1];
  3034.  
  3035.       dest += half_row_incr;
  3036.       src += half_row_incr;
  3037.       dest1 += half_row_incr;
  3038.       src1 += half_row_incr;
  3039.     }
  3040.  
  3041.     if (ditherType == MBORDERED_DITHER) {
  3042.     /*
  3043.       MBOrderedDitherDisplayCopy(vid_stream, addr,
  3044.                  1, 0, 0, 0, 0, 0,
  3045.                  vid_stream->future->display,
  3046.                  (unsigned char *) NULL);
  3047.     */
  3048.       ditherFlags[addr] = 0;
  3049.     }
  3050.   }
  3051.  
  3052.   vid_stream->mblock.recon_right_for_prev = 0;
  3053.   vid_stream->mblock.recon_down_for_prev = 0;
  3054. }
  3055.  
  3056.  
  3057.  
  3058.  
  3059. /*
  3060.  *--------------------------------------------------------------
  3061.  *
  3062.  * ProcessSkippedBFrameMBlocks --
  3063.  *
  3064.  *    Processes skipped macroblocks in B frames.
  3065.  *
  3066.  * Results:
  3067.  *    Calculates pixel values for luminance, Cr, and Cb planes
  3068.  *      in current pict image for skipped macroblocks.
  3069.  *
  3070.  * Side effects:
  3071.  *    Pixel values in pict image changed.
  3072.  *
  3073.  *--------------------------------------------------------------
  3074.  */
  3075.  
  3076. static void
  3077. ProcessSkippedBFrameMBlocks(vid_stream)
  3078.   VidStream *vid_stream;
  3079. {
  3080.   int row_size, half_row, mb_row, mb_col, row, col, rr;
  3081.   int right_half_for, down_half_for, c_right_half_for, c_down_half_for;
  3082.   int right_half_back, down_half_back, c_right_half_back, c_down_half_back;
  3083.   int addr, right_for, down_for;
  3084.   int recon_right_for, recon_down_for;
  3085.   int recon_right_back, recon_down_back;
  3086.   int right_back, down_back;
  3087.   int c_right_for, c_down_for;
  3088.   int c_right_back, c_down_back;
  3089.   unsigned char forw_lum[256];
  3090.   unsigned char forw_cr[64], forw_cb[64];
  3091.   unsigned char back_lum[256], back_cr[64], back_cb[64];
  3092.   int row_incr, half_row_incr;
  3093.   int ccol, crow;
  3094.  
  3095.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  3096.  
  3097.   row_size = vid_stream->mb_width << 4;
  3098.   half_row = (row_size >> 1);
  3099.   row_incr = row_size >> 2;
  3100.   half_row_incr =  half_row >> 2;
  3101.  
  3102.   /* Establish motion vector codes based on full pixel flag. */
  3103.  
  3104.   if (vid_stream->picture.full_pel_forw_vector) {
  3105.     recon_right_for = vid_stream->mblock.recon_right_for_prev << 1;
  3106.     recon_down_for = vid_stream->mblock.recon_down_for_prev << 1;
  3107.   } else {
  3108.     recon_right_for = vid_stream->mblock.recon_right_for_prev;
  3109.     recon_down_for = vid_stream->mblock.recon_down_for_prev;
  3110.   }
  3111.  
  3112.   if (vid_stream->picture.full_pel_back_vector) {
  3113.     recon_right_back = vid_stream->mblock.recon_right_back_prev << 1;
  3114.     recon_down_back = vid_stream->mblock.recon_down_back_prev << 1;
  3115.   } else {
  3116.     recon_right_back = vid_stream->mblock.recon_right_back_prev;
  3117.     recon_down_back = vid_stream->mblock.recon_down_back_prev;
  3118.   }
  3119.  
  3120.  
  3121.   /* Calculate motion vectors. */
  3122.   
  3123.   if (vid_stream->mblock.bpict_past_forw) {
  3124.     right_for = recon_right_for >> 1;
  3125.     down_for = recon_down_for >> 1;
  3126.     right_half_for = recon_right_for & 0x1;
  3127.     down_half_for = recon_down_for & 0x1;
  3128.     
  3129.     recon_right_for /= 2;
  3130.     recon_down_for /= 2;
  3131.     c_right_for = recon_right_for >> 1;
  3132.     c_down_for = recon_down_for >> 1;
  3133.     c_right_half_for = recon_right_for & 0x1;
  3134.     c_down_half_for = recon_down_for & 0x1;
  3135.     
  3136.   }
  3137.   if (vid_stream->mblock.bpict_past_back) {
  3138.     right_back = recon_right_back >> 1;
  3139.     down_back = recon_down_back >> 1;
  3140.     right_half_back = recon_right_back & 0x1;
  3141.     down_half_back = recon_down_back & 0x1;
  3142.     
  3143.     recon_right_back /= 2;
  3144.     recon_down_back /= 2;
  3145.     c_right_back = recon_right_back >> 1;
  3146.     c_down_back = recon_down_back >> 1;
  3147.     c_right_half_back = recon_right_back & 0x1;
  3148.     c_down_half_back = recon_down_back & 0x1;
  3149.     
  3150.   }
  3151.   /* For each skipped macroblock, do... */
  3152.   
  3153.   for (addr = vid_stream->mblock.past_mb_addr + 1;
  3154.        addr < vid_stream->mblock.mb_address; addr++) {
  3155.  
  3156.     if (opts&COLLECTING&BLOCK_INFO) {
  3157.       blks.block++;
  3158.       fprintf(block_fp,"block %d %c %d 0 skip\n",
  3159.           blks.block-1,"0IPBD"[vid_stream->picture.code_type],
  3160.           blks.qs);
  3161.     }
  3162.  
  3163.     /* Calculate macroblock row and col. */
  3164.     
  3165.     mb_row = addr / vid_stream->mb_width;
  3166.     mb_col = addr % vid_stream->mb_width;
  3167.     
  3168.     /* Calculate upper left pixel row,col for luminance plane. */
  3169.     
  3170.     row = mb_row << 4;
  3171.     col = mb_col << 4;
  3172.     crow = row / 2;
  3173.     ccol = col / 2;
  3174.     
  3175.     /* If forward predicted, calculate prediction values. */
  3176.     
  3177.     if (vid_stream->mblock.bpict_past_forw) {
  3178.       
  3179.       ReconSkippedBlock(vid_stream->past->luminance, forw_lum,
  3180.             row, col, row_size, right_for, down_for,
  3181.             right_half_for, down_half_for, 16);
  3182.       ReconSkippedBlock(vid_stream->past->Cr, forw_cr, crow,
  3183.             ccol, half_row,
  3184.             c_right_for, c_down_for, c_right_half_for, c_down_half_for, 8);
  3185.       ReconSkippedBlock(vid_stream->past->Cb, forw_cb, crow,
  3186.             ccol, half_row,
  3187.             c_right_for, c_down_for, c_right_half_for, c_down_half_for, 8);
  3188.     }
  3189.     /* If back predicted, calculate prediction values. */
  3190.     
  3191.     if (vid_stream->mblock.bpict_past_back) {
  3192.       ReconSkippedBlock(vid_stream->future->luminance, back_lum,
  3193.             row, col, row_size, right_back, down_back,
  3194.             right_half_back, down_half_back, 16);
  3195.       ReconSkippedBlock(vid_stream->future->Cr, back_cr, crow,
  3196.             ccol, half_row,
  3197.             c_right_back, c_down_back,
  3198.             c_right_half_back, c_down_half_back, 8);
  3199.       ReconSkippedBlock(vid_stream->future->Cb, back_cb, crow,
  3200.             ccol, half_row,
  3201.             c_right_back, c_down_back,
  3202.             c_right_half_back, c_down_half_back, 8);
  3203.     }
  3204.     if (vid_stream->mblock.bpict_past_forw &&
  3205.     !vid_stream->mblock.bpict_past_back) {
  3206.       
  3207.       int *dest, *dest1;
  3208.       int *src, *src1;
  3209.       dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
  3210.       src = (int *)forw_lum;
  3211.       
  3212.       for (rr = 0; rr < 16; rr++) {
  3213.     
  3214.     /* memcpy(dest, forw_lum+(rr<<4), 16);  */
  3215.     dest[0] = src[0];
  3216.     dest[1] = src[1];
  3217.     dest[2] = src[2];
  3218.     dest[3] = src[3];
  3219.     dest += row_incr;
  3220.     src += 4;
  3221.       }
  3222.       
  3223.       dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
  3224.       dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
  3225.       src = (int *)forw_cr;
  3226.       src1 = (int *)forw_cb;
  3227.       
  3228.       for (rr = 0; rr < 8; rr++) {
  3229.     /*
  3230.      * memcpy(dest, forw_cr+(rr<<3), 8); memcpy(dest1, forw_cb+(rr<<3),
  3231.      * 8);
  3232.      */
  3233.     
  3234.     dest[0] = src[0];
  3235.     dest[1] = src[1];
  3236.     
  3237.     dest1[0] = src1[0];
  3238.     dest1[1] = src1[1];
  3239.     
  3240.     dest += half_row_incr;
  3241.     dest1 += half_row_incr;
  3242.     src += 2;
  3243.     src1 += 2;
  3244.       }
  3245.     } else if (vid_stream->mblock.bpict_past_back &&
  3246.            !vid_stream->mblock.bpict_past_forw) {
  3247.       
  3248.       int *src, *src1;
  3249.       int *dest, *dest1;
  3250.       dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
  3251.       src = (int *)back_lum;
  3252.       
  3253.       for (rr = 0; rr < 16; rr++) {
  3254.     dest[0] = src[0];
  3255.     dest[1] = src[1];
  3256.     dest[2] = src[2];
  3257.     dest[3] = src[3];
  3258.     dest += row_incr;
  3259.     src += 4;
  3260.       }
  3261.       
  3262.       
  3263.       dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
  3264.       dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
  3265.       src = (int *)back_cr;
  3266.       src1 = (int *)back_cb;
  3267.       
  3268.       for (rr = 0; rr < 8; rr++) {
  3269.     /*
  3270.      * memcpy(dest, back_cr+(rr<<3), 8); memcpy(dest1, back_cb+(rr<<3),
  3271.      * 8);
  3272.      */
  3273.     
  3274.     dest[0] = src[0];
  3275.     dest[1] = src[1];
  3276.     
  3277.     dest1[0] = src1[0];
  3278.     dest1[1] = src1[1];
  3279.     
  3280.     dest += half_row_incr;
  3281.     dest1 += half_row_incr;
  3282.     src += 2;
  3283.     src1 += 2;
  3284.       }
  3285.     } else {
  3286.       
  3287.       unsigned char *src1, *src2, *src1a, *src2a;
  3288.       unsigned char *dest, *dest1;
  3289.       dest = vid_stream->current->luminance + (row * row_size) + col;
  3290.       src1 = forw_lum;
  3291.       src2 = back_lum;
  3292.       
  3293.       for (rr = 0; rr < 16; rr++) {
  3294.     dest[0] = (int) (src1[0] + src2[0]) >> 1;
  3295.     dest[1] = (int) (src1[1] + src2[1]) >> 1;
  3296.     dest[2] = (int) (src1[2] + src2[2]) >> 1;
  3297.     dest[3] = (int) (src1[3] + src2[3]) >> 1;
  3298.     dest[4] = (int) (src1[4] + src2[4]) >> 1;
  3299.     dest[5] = (int) (src1[5] + src2[5]) >> 1;
  3300.     dest[6] = (int) (src1[6] + src2[6]) >> 1;
  3301.     dest[7] = (int) (src1[7] + src2[7]) >> 1;
  3302.     dest[8] = (int) (src1[8] + src2[8]) >> 1;
  3303.     dest[9] = (int) (src1[9] + src2[9]) >> 1;
  3304.     dest[10] = (int) (src1[10] + src2[10]) >> 1;
  3305.     dest[11] = (int) (src1[11] + src2[11]) >> 1;
  3306.     dest[12] = (int) (src1[12] + src2[12]) >> 1;
  3307.     dest[13] = (int) (src1[13] + src2[13]) >> 1;
  3308.     dest[14] = (int) (src1[14] + src2[14]) >> 1;
  3309.     dest[15] = (int) (src1[15] + src2[15]) >> 1;
  3310.     dest += row_size;
  3311.     src1 += 16;
  3312.     src2 += 16;
  3313.       }
  3314.       
  3315.       
  3316.       dest = vid_stream->current->Cr + (crow * half_row) + ccol;
  3317.       dest1 = vid_stream->current->Cb + (crow * half_row) + ccol;
  3318.       src1 = forw_cr;
  3319.       src2 = back_cr;
  3320.       src1a = forw_cb;
  3321.       src2a = back_cb;
  3322.       
  3323.       for (rr = 0; rr < 8; rr++) {
  3324.     dest[0] = (int) (src1[0] + src2[0]) >> 1;
  3325.     dest[1] = (int) (src1[1] + src2[1]) >> 1;
  3326.     dest[2] = (int) (src1[2] + src2[2]) >> 1;
  3327.     dest[3] = (int) (src1[3] + src2[3]) >> 1;
  3328.     dest[4] = (int) (src1[4] + src2[4]) >> 1;
  3329.     dest[5] = (int) (src1[5] + src2[5]) >> 1;
  3330.     dest[6] = (int) (src1[6] + src2[6]) >> 1;
  3331.     dest[7] = (int) (src1[7] + src2[7]) >> 1;
  3332.     dest += half_row;
  3333.     src1 += 8;
  3334.     src2 += 8;
  3335.     
  3336.     dest1[0] = (int) (src1a[0] + src2a[0]) >> 1;
  3337.     dest1[1] = (int) (src1a[1] + src2a[1]) >> 1;
  3338.     dest1[2] = (int) (src1a[2] + src2a[2]) >> 1;
  3339.     dest1[3] = (int) (src1a[3] + src2a[3]) >> 1;
  3340.     dest1[4] = (int) (src1a[4] + src2a[4]) >> 1;
  3341.     dest1[5] = (int) (src1a[5] + src2a[5]) >> 1;
  3342.     dest1[6] = (int) (src1a[6] + src2a[6]) >> 1;
  3343.     dest1[7] = (int) (src1a[7] + src2a[7]) >> 1;
  3344.     dest1 += half_row;
  3345.     src1a += 8;
  3346.     src2a += 8;
  3347.       }
  3348.     }
  3349.     
  3350.     if (ditherType == MBORDERED_DITHER) {
  3351.       ditherFlags[addr] = 1;
  3352.     }
  3353.   }
  3354. }
  3355.  
  3356.  
  3357.  
  3358.  
  3359. /*
  3360.  *--------------------------------------------------------------
  3361.  *
  3362.  * ReconSkippedBlock --
  3363.  *
  3364.  *    Reconstructs predictive block for skipped macroblocks
  3365.  *      in B Frames.
  3366.  *
  3367.  * Results:
  3368.  *    No return values.
  3369.  *
  3370.  * Side effects:
  3371.  *    None.
  3372.  *
  3373.  *--------------------------------------------------------------
  3374.  */
  3375.  
  3376. static void
  3377. ReconSkippedBlock(source, dest, row, col, row_size,
  3378.           right, down, right_half, down_half, width)
  3379.   unsigned char *source;
  3380.   unsigned char *dest;
  3381.   int row, col, row_size, right, down, right_half, down_half, width;
  3382. {
  3383.   int rr;
  3384.   unsigned char *source2;
  3385.  
  3386.   source += ((row + down) * row_size) + col + right;
  3387.  
  3388.   if (width == 16) {
  3389.     if ((!right_half) && (!down_half)) {
  3390.     if (right & 0x1) {
  3391.       /* No alignment, use bye copy */
  3392.       for (rr = 0; rr < 16; rr++) {
  3393.         dest[0] = source[0];
  3394.         dest[1] = source[1];
  3395.         dest[2] = source[2];
  3396.         dest[3] = source[3];
  3397.         dest[4] = source[4];
  3398.         dest[5] = source[5];
  3399.         dest[6] = source[6];
  3400.         dest[7] = source[7];
  3401.         dest[8] = source[8];
  3402.         dest[9] = source[9];
  3403.         dest[10] = source[10];
  3404.         dest[11] = source[11];
  3405.         dest[12] = source[12];
  3406.         dest[13] = source[13];
  3407.         dest[14] = source[14];
  3408.         dest[15] = source[15];
  3409.         dest += 16;
  3410.         source += row_size;
  3411.       }
  3412.     } else if (right & 0x2) {
  3413.       /* Half-word bit aligned, use 16 bit copy */
  3414.       short *src = (short *)source;
  3415.       short *d = (short *)dest;
  3416.       row_size >>= 1;
  3417.       for (rr = 0; rr < 16; rr++) {
  3418.         d[0] = src[0];
  3419.         d[1] = src[1];
  3420.         d[2] = src[2];
  3421.         d[3] = src[3];
  3422.         d[4] = src[4];
  3423.         d[5] = src[5];
  3424.         d[6] = src[6];
  3425.         d[7] = src[7];
  3426.         d += 8;
  3427.         src += row_size;
  3428.       }
  3429.     } else {
  3430.       /* Word aligned, use 32 bit copy */
  3431.       int *src = (int *)source;
  3432.       int *d = (int *)dest;
  3433.       row_size >>= 2;
  3434.       for (rr = 0; rr < 16; rr++) {
  3435.         d[0] = src[0];
  3436.         d[1] = src[1];
  3437.         d[2] = src[2];
  3438.         d[3] = src[3];
  3439.         d += 4;
  3440.         src += row_size;
  3441.       }
  3442.     }
  3443.     } else {
  3444.       source2 = source + right_half + (row_size * down_half);
  3445.       for (rr = 0; rr < width; rr++) {
  3446.     dest[0] = (int) (source[0] + source2[0]) >> 1;
  3447.     dest[1] = (int) (source[1] + source2[1]) >> 1;
  3448.     dest[2] = (int) (source[2] + source2[2]) >> 1;
  3449.     dest[3] = (int) (source[3] + source2[3]) >> 1;
  3450.     dest[4] = (int) (source[4] + source2[4]) >> 1;
  3451.     dest[5] = (int) (source[5] + source2[5]) >> 1;
  3452.     dest[6] = (int) (source[6] + source2[6]) >> 1;
  3453.     dest[7] = (int) (source[7] + source2[7]) >> 1;
  3454.     dest[8] = (int) (source[8] + source2[8]) >> 1;
  3455.     dest[9] = (int) (source[9] + source2[9]) >> 1;
  3456.     dest[10] = (int) (source[10] + source2[10]) >> 1;
  3457.     dest[11] = (int) (source[11] + source2[11]) >> 1;
  3458.     dest[12] = (int) (source[12] + source2[12]) >> 1;
  3459.     dest[13] = (int) (source[13] + source2[13]) >> 1;
  3460.     dest[14] = (int) (source[14] + source2[14]) >> 1;
  3461.     dest[15] = (int) (source[15] + source2[15]) >> 1;
  3462.     dest += width;
  3463.     source += row_size;
  3464.     source2 += row_size;
  3465.       }
  3466.     }
  3467.   } else {            /* (width == 8) */
  3468.     assert(width == 8);
  3469.     if ((!right_half) && (!down_half)) {
  3470.       if (right & 0x1) {
  3471.     for (rr = 0; rr < width; rr++) {
  3472.       dest[0] = source[0];
  3473.       dest[1] = source[1];
  3474.       dest[2] = source[2];
  3475.       dest[3] = source[3];
  3476.       dest[4] = source[4];
  3477.       dest[5] = source[5];
  3478.       dest[6] = source[6];
  3479.       dest[7] = source[7];
  3480.       dest += 8;
  3481.       source += row_size;
  3482.     }
  3483.       } else if (right & 0x02) {
  3484.     short *d = (short *)dest;
  3485.     short *src = (short *)source;
  3486.     row_size >>= 1;
  3487.     for (rr = 0; rr < width; rr++) {
  3488.       d[0] = src[0];
  3489.       d[1] = src[1];
  3490.       d[2] = src[2];
  3491.       d[3] = src[3];
  3492.       d += 4;
  3493.       src += row_size;
  3494.     }
  3495.       } else {
  3496.     int *d = (int *)dest;
  3497.     int *src = (int *)source;
  3498.     row_size >>= 2;
  3499.     for (rr = 0; rr < width; rr++) {
  3500.       d[0] = src[0];
  3501.       d[1] = src[1];
  3502.       d += 2;
  3503.       src += row_size;
  3504.     }
  3505.       }
  3506.     } else {
  3507.       source2 = source + right_half + (row_size * down_half);
  3508.       for (rr = 0; rr < width; rr++) {
  3509.     dest[0] = (int) (source[0] + source2[0]) >> 1;
  3510.     dest[1] = (int) (source[1] + source2[1]) >> 1;
  3511.     dest[2] = (int) (source[2] + source2[2]) >> 1;
  3512.     dest[3] = (int) (source[3] + source2[3]) >> 1;
  3513.     dest[4] = (int) (source[4] + source2[4]) >> 1;
  3514.     dest[5] = (int) (source[5] + source2[5]) >> 1;
  3515.     dest[6] = (int) (source[6] + source2[6]) >> 1;
  3516.     dest[7] = (int) (source[7] + source2[7]) >> 1;
  3517.     dest += width;
  3518.     source += row_size;
  3519.     source2 += row_size;
  3520.       }
  3521.     }
  3522.   }
  3523. }
  3524.  
  3525.  
  3526.  
  3527. /*
  3528.  *--------------------------------------------------------------
  3529.  *
  3530.  * DoPictureDisplay --
  3531.  *
  3532.  *    Converts image from Lum, Cr, Cb to colormap space. Puts
  3533.  *      image in lum plane. Updates past and future frame
  3534.  *      pointers. Dithers image. Sends to display mechanism.
  3535.  *
  3536.  * Results:
  3537.  *    Pict image structure locked if displaying or if frame
  3538.  *      is needed as past or future reference.
  3539.  *
  3540.  * Side effects:
  3541.  *    Lum plane pummelled.
  3542.  *
  3543.  *--------------------------------------------------------------
  3544.  */
  3545.  
  3546. static void
  3547. DoPictureDisplay(vid_stream)
  3548.   VidStream *vid_stream;
  3549. {
  3550.   
  3551.   /* Update past and future references if needed. */
  3552.  
  3553.   if ((vid_stream->picture.code_type == I_TYPE) || 
  3554.       (vid_stream->picture.code_type == P_TYPE)) {
  3555.     if (vid_stream->future == NULL) {
  3556.       vid_stream->future = vid_stream->current;
  3557.       vid_stream->future->locked |= FUTURE_LOCK;
  3558.     } else {
  3559.       if (vid_stream->past != NULL) {
  3560.     vid_stream->past->locked &= ~PAST_LOCK;
  3561.       }
  3562.       vid_stream->past = vid_stream->future;
  3563.       vid_stream->past->locked &= ~FUTURE_LOCK;
  3564.       vid_stream->past->locked |= PAST_LOCK;
  3565.       vid_stream->future = vid_stream->current;
  3566.       vid_stream->future->locked |= FUTURE_LOCK;
  3567.       vid_stream->current = vid_stream->past;
  3568.       /* OLD: ShowOutputVal(vid_stream); */
  3569.     }
  3570.   } else {
  3571.     /* OLD ShowOutputVal(vid_stream); */
  3572.     }
  3573. }
  3574.